aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x._CHANGELOGbin0 -> 1505 bytes
-rwxr-xr-x._LICENSEbin0 -> 167 bytes
-rwxr-xr-x._READMEbin0 -> 1505 bytes
-rwxr-xr-x._ptunnel.8bin0 -> 167 bytes
-rwxr-xr-x._ptunnel.cbin0 -> 167 bytes
-rwxr-xr-x._ptunnel.hbin0 -> 167 bytes
-rw-r--r--.pc/.quilt_patches1
-rw-r--r--.pc/.quilt_series1
-rw-r--r--.pc/.version1
-rwxr-xr-x.pc/add_hardening_flags.diff/Makefile55
-rw-r--r--.pc/applied-patches4
-rwxr-xr-x.pc/fix_minus_chars_in_man.patch/ptunnel.8123
-rwxr-xr-x.pc/fix_typo.diff/README118
-rwxr-xr-x.pc/makefile-debian-prefix.patch/Makefile55
-rwxr-xr-xCHANGELOG94
-rwxr-xr-xLICENSE28
-rwxr-xr-xMakefile55
-rwxr-xr-xREADME118
-rw-r--r--debian/changelog80
-rw-r--r--debian/compat1
-rw-r--r--debian/control22
-rw-r--r--debian/copyright58
-rw-r--r--debian/patches/add_hardening_flags.diff28
-rw-r--r--debian/patches/fix_minus_chars_in_man.patch72
-rw-r--r--debian/patches/fix_typo.diff15
-rw-r--r--debian/patches/makefile-debian-prefix.patch17
-rw-r--r--debian/patches/series4
-rw-r--r--debian/ptunnel.doc-base10
-rw-r--r--debian/ptunnel.docs4
-rwxr-xr-xdebian/rules11
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch5
-rwxr-xr-xmd5.c381
-rwxr-xr-xmd5.h91
-rwxr-xr-xptunnel.8123
-rwxr-xr-xptunnel.c1622
-rwxr-xr-xptunnel.h419
-rw-r--r--redhat/._ptunnel.specbin0 -> 499 bytes
-rw-r--r--redhat/ptunnel.spec71
-rw-r--r--selinux/CVS/Entries2
-rw-r--r--selinux/CVS/Repository1
-rw-r--r--selinux/CVS/Root1
-rw-r--r--selinux/ptunnel.te22
-rwxr-xr-xweb/._index.htmlbin0 -> 82 bytes
-rwxr-xr-xweb/._setup.pngbin0 -> 82 bytes
-rwxr-xr-xweb/index.html266
-rwxr-xr-xweb/packet-format.pngbin0 -> 4340 bytes
-rwxr-xr-xweb/setup.pngbin0 -> 14808 bytes
48 files changed, 3980 insertions, 0 deletions
diff --git a/._CHANGELOG b/._CHANGELOG
new file mode 100755
index 0000000..c99a132
--- /dev/null
+++ b/._CHANGELOG
Binary files differ
diff --git a/._LICENSE b/._LICENSE
new file mode 100755
index 0000000..1fdbfdc
--- /dev/null
+++ b/._LICENSE
Binary files differ
diff --git a/._README b/._README
new file mode 100755
index 0000000..86f9c18
--- /dev/null
+++ b/._README
Binary files differ
diff --git a/._ptunnel.8 b/._ptunnel.8
new file mode 100755
index 0000000..2cbd7e8
--- /dev/null
+++ b/._ptunnel.8
Binary files differ
diff --git a/._ptunnel.c b/._ptunnel.c
new file mode 100755
index 0000000..63e1130
--- /dev/null
+++ b/._ptunnel.c
Binary files differ
diff --git a/._ptunnel.h b/._ptunnel.h
new file mode 100755
index 0000000..63e1130
--- /dev/null
+++ b/._ptunnel.h
Binary files differ
diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/add_hardening_flags.diff/Makefile b/.pc/add_hardening_flags.diff/Makefile
new file mode 100755
index 0000000..01612d7
--- /dev/null
+++ b/.pc/add_hardening_flags.diff/Makefile
@@ -0,0 +1,55 @@
+# Makefile for the pingtunnel utility
+# (c) 2004-2009 Daniel Stoedle, daniels@cs.uit.no
+# ptunnel.exe target added by Mike Miller, mike@mikeage.net
+
+CC = gcc
+CFLAGS = -Wall -g
+LDOPTS = -lpthread -lpcap
+PT_OBJS = ptunnel.o md5.o
+
+WIN32_CC = mingw32-gcc
+WIN32_CFLAGS = -g -Wall -DWIN32 -I"c:\Program Files\WpdPack\Include"
+WIN32_LDOPTS = -lwpcap -lwsock32 -L"c:\Program Files\WpdPack\Lib"
+WIN32_PT_OBJS = ptunnel.obj md5.obj
+
+prefix = /usr
+bindir = $(prefix)/bin
+mandir = $(prefix)/share/man/man8
+
+all: ptunnel
+
+dist:
+ rm -rf PingTunnel/
+ mkdir PingTunnel
+ cp ptunnel.c ptunnel.h Makefile.dist PingTunnel/
+ mv PingTunnel/Makefile.dist PingTunnel/Makefile
+
+
+install: ptunnel
+ install -d $(bindir)/
+ install -d $(mandir)/
+ install ./ptunnel $(bindir)/ptunnel
+ install ./ptunnel.8 $(mandir)/ptunnel.8
+
+ptunnel: $(PT_OBJS)
+ $(CC) -o $@ $^ $(LDOPTS) `[ -e /usr/include/selinux/selinux.h ] && echo -lselinux`
+
+ptunnel.exe: $(WIN32_PT_OBJS)
+ $(CC) -o $@ $^ $(WIN32_LDOPTS)
+
+clean:
+ -rm -f *.o ptunnel
+ -rm -f *.obj ptunnel.exe
+ -rm -f .depend
+
+depend: .depend
+.depend:
+ $(CC) $(CFLAGS) -MM *.c > $@
+
+%.o:%.c
+ $(CC) $(CFLAGS) `[ -e /usr/include/selinux/selinux.h ] && echo -DHAVE_SELINUX` -c -o $@ $<
+
+%.obj:%.c
+ $(WIN32_CC) $(WIN32_CFLAGS) -c -o $@ $<
+
+-include .depend
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..9a8f77a
--- /dev/null
+++ b/.pc/applied-patches
@@ -0,0 +1,4 @@
+add_hardening_flags.diff
+fix_typo.diff
+fix_minus_chars_in_man.patch
+makefile-debian-prefix.patch
diff --git a/.pc/fix_minus_chars_in_man.patch/ptunnel.8 b/.pc/fix_minus_chars_in_man.patch/ptunnel.8
new file mode 100755
index 0000000..dff91e5
--- /dev/null
+++ b/.pc/fix_minus_chars_in_man.patch/ptunnel.8
@@ -0,0 +1,123 @@
+.TH ptunnel 8 "September 5, 2011" "Version 0.72" "Yellow Lemon Software"
+.SH NAME
+ptunnel \- tunnel TCP connections over ICMP echo request/reply packets.
+.SH SYNOPSIS
+.B ptunnel
+\-p proxy_address \-lp listen_port \-da destination_address \-dp dest_port [\-c network_device] [\-v verbosity] [-f file] [-udp] [-syslog]
+
+.B ptunnel
+[\-c network_device] [\-v verbosity] [\-f file] [\-udp] [\-syslog] [\-daemon file]
+
+.B ptunnel
+[\-u] [\-x password] [\-setuid user] [\-setgid group] [\-chroot dir] [\-setcon context]
+
+.B ptunnel
+\-h
+.SH DESCRIPTION
+ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. At first glance, this might seem like a rather useless thing to do, but it can actually come in handy in some cases. The following example illustrates the main motivation in creating ptunnel:
+.PP
+Setting: You're on the go, and stumble across an open wireless network. The network gives you an IP address, but won't let you send TCP or UDP packets out to the rest of the internet, for instance to check your mail. What to do? By chance, you discover that the network will allow you to ping any computer on the rest of the internet. With ptunnel, you can utilize this feature to check your mail, or do other things that require TCP.
+.SH OPTIONS
+.TP
+.SH Client options:
+.TP
+.B \-p proxy_address
+Specify the host on which the proxy is running.
+.TP
+.B \-lp listen_port
+Specifies the port on which the client will listen for incoming TCP connections.
+.TP
+.B \-da destination_addr
+Specifies the address to which you want your packets tunneled after reaching the proxy when in client mode, or restricts the destination packets can be forwarded to when in server mode.
+.TP
+.B \-dp destination_port
+Specifies/restrict the port that the proxy should tunnel the TCP connection to.
+.TP
+.SH Shared options:
+.TP
+.B \-c network_device
+Specify the network interface to capture packets from. Note that packet capturing isn't always necessary, but you should try this if you experience problems with ptunnel.
+.TP
+.B \-v verbosity
+Controls the verbosity level. -1 is no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives.
+.TP
+.B \-udp
+Enables tunneling over UDP port 53 (DNS) instead of using ICMP. This will only work if your proxy can accept incoming traffic on port 53, and the client is able to send data to the proxy on port 53. Note that this option does not wrap ptunnel's data in DNS-compliant packets. This option must be given on both the proxy and client side for things to work correctly.
+.TP
+.B \-syslog (Not available on Windows.)
+Changes logging to use the built-in syslog fascility.
+.TP
+.B \-daemon file (Not available on Windows.)
+Run in background, writing PID in file.
+.TP
+.B \-u
+Attempts to run ptunnel without privileges. This doesn't usually work! On UNIX systems please consider using the following three options instead:
+.TP
+.B \-setuid user (Not available on Windows.)
+When started in privileged mode, drop down to user's rights as soon as possible.
+.TP
+.B \-setgid group (Not available on Windows.)
+When started in privileged mode, drop down to group's rights as soon as possible.
+.TP
+.B \-chroot dir (Not available on Windows.)
+When started in privileged mode, restrict file access to the specified directory.
+.TP
+.B \-setcon context (Not available on Windows.)
+Set SELinux context when all there is left to do are network I/O operations.
+In order to be able to combine with -chroot you will have to `mount --bind /proc /chrootdir/proc`
+.TP
+.B \-x password
+Specifies a password or passphrase to use. This will allow you to protect the proxy from use by others who don't know the password. It needs to be specified on both proxy and client.
+.TP
+.B \-f file
+Specifies a log file. If you specify -syslog, syslog is always used instead.
+.TP
+.B \-h
+Displays brief usage information.
+
+.SH EXAMPLES
+The following assumes that ptunnel is run as root, both on the proxy and client. To tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used:
+.TP
+.B ptunnel \-p proxy.pingtunnel.com \-lp 8000 \-da login.domain.com \-dp 22
+.PP
+An ssh connection to login.domain.com can now be established as follows:
+.TP
+.B ssh \-p 8000 localhost
+.PP
+If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts.
+
+Of course, for all of this to work, you need to start the proxy on your proxy-computer (proxy.pingtunnel.com). Doing this is very simple:
+
+.B ptunnel
+
+If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -c switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On Mac OS X, packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise.
+
+To protect yourself from others using your proxy, you can protect access to it with a password using the <tt>-x</tt> switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.
+
+.SH EXIT STATUS
+.B ptunnel
+does not exit until forced to do so by an interrupt (Ctrl-C) or if it crashes.
+.SH BUGS
+.B ptunnel
+currently does not handle packet capturing on network interfaces other than ethernet or wireless correctly.
+.SH AUTHORS AND CONTRIBUTORS
+Daniel Stoedle (daniels@cs.uit.no)
+
+Windows port: Mike Miller (mike@mikeage.net)
+
+SELinux support: Sebastien Raveau (sebastien.raveau@epita.fr)
+
+Patches: Joe McKenzie, Steffen Wendzel and StalkR.
+
+.SH LICENSE
+.B ptunnel
+is licensed under the BSD License.
+.SH AVAILABILITY
+.TP
+The ptunnel homepage is currently located here:
+http://www.cs.uit.no/~daniels/PingTunnel/
+.TP
+The freshmeat project page is located here:
+http://freshmeat.net/projects/ptunnel/
+.PP
+Please take the time to rate ptunnel if you find it useful. Thanks!
diff --git a/.pc/fix_typo.diff/README b/.pc/fix_typo.diff/README
new file mode 100755
index 0000000..985464a
--- /dev/null
+++ b/.pc/fix_typo.diff/README
@@ -0,0 +1,118 @@
+PingTunnel Read Me
+==================
+
+What is ptunnel?
+----------------
+Ptunnel is an application that allows you to reliably tunnel TCP connections
+to a remote host using ICMP echo request and reply packets, commonly known as
+ping requests and replies.
+
+
+Contact details
+---------------
+You can the author, Daniel Stoedle, here:
+ <daniels@cs.uit.no>
+The official ptunnel website is located here:
+ <http://www.cs.uit.no/~daniels/PingTunnel/>
+The Windows port was created by Mike Miller:
+ <mike@mikeage.net>
+
+
+Compiling
+---------
+To compile ptunnel, simply run make. If everything goes well, you should end up
+with a binary called ptunnel. This serves as both the client and proxy. You can
+optionally install it using "make install". On Windows, run "make ptunnel.exe"
+to compile the Windows binary. You will need mingw installed, as well as the
+WinPcap library. WinPcap is available here:
+ <http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip>
+
+
+Running
+-------
+Ptunnel works best when running as root, and usually requires running as root.
+Again, from the website:
+
+Client: ./ptunnel -p <proxy address> -lp <listen port> -da <destination address>
+ -dp <dest port> [-c <network device>] [-v <verbosity>] [-u]
+ [-x password]
+Proxy: ./ptunnel [-c <network device>] [-v <verbosity>] [-u] [-x password]
+
+The -p switch sets the address of the host on which the proxy is running. A
+quick test to see if the proxy will work is simply to try pinging this host -
+if you get replies, you should be able to make the tunnel work.
+
+The -lp, -da and -dp switches set the local listening port, destination address
+and destination port. For instance, to tunnel ssh connections from the client
+machine via a proxy running on proxy.pingtunnel.com to the computer
+login.domain.com, the following command line would be used:
+
+sudo ./ptunnel -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22
+
+An ssh connection to login.domain.com can now be established as follows:
+
+ssh -p 8000 localhost
+
+If ssh complains about potential man-in-the-middle attacks, simply remove the
+offending key from the known_hosts file. The warning/error is expected if you
+have previously ssh'd to your local computer (i.e., ssh localhost), or you have
+used ptunnel to forward ssh connections to different hosts.
+
+Of course, for all of this to work, you need to start the proxy on your
+proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is very
+simple:
+
+sudo ./ptunnel
+
+If you find that the proxy isn't working, you will need to enable packet
+capturing on the main network device. Currently this device is assumed to be
+an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by
+giving the -c switch, and supplying the device name to capture packets on (for
+instance eth0 or en1). The same goes for the client. On versions of Mac OS X
+prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy
+and client), as resent packets won't be received otherwise.
+
+To protect yourself from others using your proxy, you can protect access to it
+with a password using the <tt>-x</tt> switch. The password is never sent in
+the clear, but keep in mind that it may be visible from tools like top or ps,
+which can display the command line used to start an application.
+
+Finally, the -u switch will attempt to run the proxy in unprivileged mode (i.e.,
+no need for root access), and the -v switch controls the amount of output from
+ptunnel. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2
+gives more output, 3 provides even more output, level 4 displays debug info and
+level 5 displays absolutely everything, including the nasty details of sends and
+receives. The -f switch allows output to be saved to a logfile.
+
+Security features: Please see the ptunnel man-page for instructions.
+
+
+Supported operating systems
+---------------------------
+Ptunnel supports most operating systems with libpcap, the usual POSIX functions
+and a BSD sockets compatible API. In particular, it has been tested on Linux
+Fedora Core 2 and Mac OS X 10.3.6 and above. As of version 0.7, ptunnel can also
+be compiled on Windows, courtesy of Mike Miller, assuming mingw and WinPcap is
+installed.
+
+
+Credits and contributors
+------------------------
+Thanks to L. Peter Deutsch for his open-source MD5 implementation, included with
+ptunnel, but also available here:
+http://sourceforge.net/projects/libmd5-rfc/
+
+Many thanks also to Mike Miller <mike@mikeage.net> for his work on creating a
+Windows port of ptunnel.
+
+Thanks to Sebastien Raveau <sebastien.raveau@epita.fr> for implementing various
+security features and SELinux support.
+
+Also thanks to Joe McKenzie, Steffen Wendzel and StalkR for contributing patches to
+ptunnel.
+
+License
+-------
+Ping Tunnel is Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
+Yellow Lemon Software. All rights reserved. Ping Tunnel is licensed under the
+BSD License. Please see the LICENSE file for details.
diff --git a/.pc/makefile-debian-prefix.patch/Makefile b/.pc/makefile-debian-prefix.patch/Makefile
new file mode 100755
index 0000000..e9c1b7a
--- /dev/null
+++ b/.pc/makefile-debian-prefix.patch/Makefile
@@ -0,0 +1,55 @@
+# Makefile for the pingtunnel utility
+# (c) 2004-2009 Daniel Stoedle, daniels@cs.uit.no
+# ptunnel.exe target added by Mike Miller, mike@mikeage.net
+
+CC = gcc
+CFLAGS = -Wall -g
+LDOPTS = -lpthread -lpcap
+PT_OBJS = ptunnel.o md5.o
+
+WIN32_CC = mingw32-gcc
+WIN32_CFLAGS = -g -Wall -DWIN32 -I"c:\Program Files\WpdPack\Include"
+WIN32_LDOPTS = -lwpcap -lwsock32 -L"c:\Program Files\WpdPack\Lib"
+WIN32_PT_OBJS = ptunnel.obj md5.obj
+
+prefix = /usr
+bindir = $(prefix)/bin
+mandir = $(prefix)/share/man/man8
+
+all: ptunnel
+
+dist:
+ rm -rf PingTunnel/
+ mkdir PingTunnel
+ cp ptunnel.c ptunnel.h Makefile.dist PingTunnel/
+ mv PingTunnel/Makefile.dist PingTunnel/Makefile
+
+
+install: ptunnel
+ install -d $(bindir)/
+ install -d $(mandir)/
+ install ./ptunnel $(bindir)/ptunnel
+ install ./ptunnel.8 $(mandir)/ptunnel.8
+
+ptunnel: $(PT_OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS) `[ -e /usr/include/selinux/selinux.h ] && echo -lselinux`
+
+ptunnel.exe: $(WIN32_PT_OBJS)
+ $(CC) -o $@ $^ $(WIN32_LDOPTS)
+
+clean:
+ -rm -f *.o ptunnel
+ -rm -f *.obj ptunnel.exe
+ -rm -f .depend
+
+depend: .depend
+.depend:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -MM *.c > $@
+
+%.o:%.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) `[ -e /usr/include/selinux/selinux.h ] && echo -DHAVE_SELINUX` -c -o $@ $<
+
+%.obj:%.c
+ $(WIN32_CC) $(WIN32_CFLAGS) -c -o $@ $<
+
+-include .depend
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100755
index 0000000..d3a3e8f
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,94 @@
+PingTunnel Changelog
+====================
+
+0.72 - 5. September 2011
+- Fixes an authentication bug that would manifest as hung connections with
+ protocols that send data from the client-side before receiving data from
+ the server-side. Thanks to StalkR for locating the bug and fixing it.
+- Fixes a crash when attempting to enable packet-capture for non-existing
+ network devices. Thanks to Steffen Wendzel for the patch.
+
+0.71 - 22. June 2009
+- Added security features and SELinux support, courtesy of Sebastien Raveau.
+
+0.70 - 12. January 2009
+- Added rudimentary support for tunneling over udp port 53.
+- Added built-in support for compiling on Windows, thanks to Mike Miller.
+- Added syslog support, also courtesy of Mike Miller.
+- Experimental support for spoofing the source IP address. The source
+ address must be explicitly configured in the source code, and it might
+ not work (which is why it's experimental). To enable, define
+ kPT_add_iphdr to 1.
+
+0.62 - [Never released]
+- Added many comments to the ptunnel header file.
+- Moved most include directives to the header file.
+- Fixed crash if proxy or destination hostnames could not be looked up.
+
+0.61 - 26. May 2005
+- Noted that ptunnel now works without packet capturing on Mac OS X 10.4
+ Tiger.
+- Log files are now opened in append-mode (i.e., not truncated).
+- Fixed a bug that could cause ptunnel to crash if passwords shorter than
+ 16 characters were used (the overwhelming majority of passwords, most
+ likely!).
+
+0.60 - 15. Apr 2005
+- Added authentication support, changing parts of the ptunnel protocol.
+- Added a manpage.
+- Added MD5 implementation by L. Peter Deutsch for authentication.
+- Moved declaration of a variable to allow ptunnel to compile cleanly
+ on gcc 2.95 - thanks Choong!
+- Added error handling for proxy connections.
+- Fixed a problem with printing send/recv info. All verbosity levels
+ should work now.
+- Updated contact info.
+
+0.55 - 18. Feb 2005
+- Fixed a locking bug that would manifest itself when the maximum
+ connection count on the proxy was reached.
+- Fixed ptunnel to compile correctly on 64-bit architectures (thanks
+ to Åsmund Grammeltvedt for pointing out the necessary changes!)
+- Added a new logging level (level 5). Level 4 no longer outputs send
+ and receive info; for this info level 5 is necessary.
+- When libpcap is in use, the interface is no longer put in promiscous
+ mode. This has never been necessary, and also makes it impossible to
+ use ptunnel with more than one client on the same network.
+- Discovered a problem with pcap that would cause ptunnel to hang when
+ pcap was in use. This problem has not been resolved; the workaround is
+ to simply re-execute the client, or disable pcap if possible.
+- Added support for specifying a log file on the command line, using
+ the -f switch.
+
+0.54 - 1. Feb 2005
+- Fixed a byte-order bug (thanks Alfred!)
+
+0.53 - 31. Jan 2005
+- Fixed a threading bug, and implemented support for limiting the
+ maximum number of tunnels.
+
+Thanks to Alfred Young for reporting and fixing the following bugs:
+- Fixed a bug with packets captured via libpcap, where the struct
+ sockaddr wasn't properly zeroed.
+- Fixed a byte order bug in create_and_insert_proxy_desc.
+- Fixed a memory leak in remove_proxy_desc.
+
+
+0.52 - 3. Jan 2005
+- Fixed a problem introduced by the ICMP ID field changes. The
+ proxy didn't retain the ID of the packets received from clients,
+ resulting in dropped ICMP packets at the router. This in turn
+ lead to the tunnel no longer working, depending on the strictness
+ of the router. This version fixes that problem.
+- Makefile is better now, thanks to Dries Verachtert.
+
+
+0.51 - 2. Jan 2005
+- Fixed incorrect checksum calculation for resent packets.
+- Stopped relying on the ICMP packet's "built-in" ID field,
+ and moved the information to the data portion of the packet.
+- Changed default verbosity level from debug to verbose.
+
+
+0.50 - 7. Dec 2004
+Initial public release.
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..c34a1e3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2004-2009, Daniel Stoedle <daniels@cs.uit.no>,
+Yellow Lemon Software. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+- Neither the name of the Yellow Lemon Software nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..0a9ed0e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,55 @@
+# Makefile for the pingtunnel utility
+# (c) 2004-2009 Daniel Stoedle, daniels@cs.uit.no
+# ptunnel.exe target added by Mike Miller, mike@mikeage.net
+
+CC = gcc
+CFLAGS = -Wall -g
+LDOPTS = -lpthread -lpcap
+PT_OBJS = ptunnel.o md5.o
+
+WIN32_CC = mingw32-gcc
+WIN32_CFLAGS = -g -Wall -DWIN32 -I"c:\Program Files\WpdPack\Include"
+WIN32_LDOPTS = -lwpcap -lwsock32 -L"c:\Program Files\WpdPack\Lib"
+WIN32_PT_OBJS = ptunnel.obj md5.obj
+
+prefix = $(DESTDIR)/usr
+bindir = $(prefix)/sbin
+mandir = $(prefix)/share/man/man8
+
+all: ptunnel
+
+dist:
+ rm -rf PingTunnel/
+ mkdir PingTunnel
+ cp ptunnel.c ptunnel.h Makefile.dist PingTunnel/
+ mv PingTunnel/Makefile.dist PingTunnel/Makefile
+
+
+install: ptunnel
+ install -d $(bindir)/
+ install -d $(mandir)/
+ install ./ptunnel $(bindir)/ptunnel
+ install ./ptunnel.8 $(mandir)/ptunnel.8
+
+ptunnel: $(PT_OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS) `[ -e /usr/include/selinux/selinux.h ] && echo -lselinux`
+
+ptunnel.exe: $(WIN32_PT_OBJS)
+ $(CC) -o $@ $^ $(WIN32_LDOPTS)
+
+clean:
+ -rm -f *.o ptunnel
+ -rm -f *.obj ptunnel.exe
+ -rm -f .depend
+
+depend: .depend
+.depend:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -MM *.c > $@
+
+%.o:%.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) `[ -e /usr/include/selinux/selinux.h ] && echo -DHAVE_SELINUX` -c -o $@ $<
+
+%.obj:%.c
+ $(WIN32_CC) $(WIN32_CFLAGS) -c -o $@ $<
+
+-include .depend
diff --git a/README b/README
new file mode 100755
index 0000000..688da91
--- /dev/null
+++ b/README
@@ -0,0 +1,118 @@
+PingTunnel Read Me
+==================
+
+What is ptunnel?
+----------------
+Ptunnel is an application that allows you to reliably tunnel TCP connections
+to a remote host using ICMP echo request and reply packets, commonly known as
+ping requests and replies.
+
+
+Contact details
+---------------
+You can contact the author, Daniel Stoedle, here:
+ <daniels@cs.uit.no>
+The official ptunnel website is located here:
+ <http://www.cs.uit.no/~daniels/PingTunnel/>
+The Windows port was created by Mike Miller:
+ <mike@mikeage.net>
+
+
+Compiling
+---------
+To compile ptunnel, simply run make. If everything goes well, you should end up
+with a binary called ptunnel. This serves as both the client and proxy. You can
+optionally install it using "make install". On Windows, run "make ptunnel.exe"
+to compile the Windows binary. You will need mingw installed, as well as the
+WinPcap library. WinPcap is available here:
+ <http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip>
+
+
+Running
+-------
+Ptunnel works best when running as root, and usually requires running as root.
+Again, from the website:
+
+Client: ./ptunnel -p <proxy address> -lp <listen port> -da <destination address>
+ -dp <dest port> [-c <network device>] [-v <verbosity>] [-u]
+ [-x password]
+Proxy: ./ptunnel [-c <network device>] [-v <verbosity>] [-u] [-x password]
+
+The -p switch sets the address of the host on which the proxy is running. A
+quick test to see if the proxy will work is simply to try pinging this host -
+if you get replies, you should be able to make the tunnel work.
+
+The -lp, -da and -dp switches set the local listening port, destination address
+and destination port. For instance, to tunnel ssh connections from the client
+machine via a proxy running on proxy.pingtunnel.com to the computer
+login.domain.com, the following command line would be used:
+
+sudo ./ptunnel -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22
+
+An ssh connection to login.domain.com can now be established as follows:
+
+ssh -p 8000 localhost
+
+If ssh complains about potential man-in-the-middle attacks, simply remove the
+offending key from the known_hosts file. The warning/error is expected if you
+have previously ssh'd to your local computer (i.e., ssh localhost), or you have
+used ptunnel to forward ssh connections to different hosts.
+
+Of course, for all of this to work, you need to start the proxy on your
+proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is very
+simple:
+
+sudo ./ptunnel
+
+If you find that the proxy isn't working, you will need to enable packet
+capturing on the main network device. Currently this device is assumed to be
+an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by
+giving the -c switch, and supplying the device name to capture packets on (for
+instance eth0 or en1). The same goes for the client. On versions of Mac OS X
+prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy
+and client), as resent packets won't be received otherwise.
+
+To protect yourself from others using your proxy, you can protect access to it
+with a password using the <tt>-x</tt> switch. The password is never sent in
+the clear, but keep in mind that it may be visible from tools like top or ps,
+which can display the command line used to start an application.
+
+Finally, the -u switch will attempt to run the proxy in unprivileged mode (i.e.,
+no need for root access), and the -v switch controls the amount of output from
+ptunnel. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2
+gives more output, 3 provides even more output, level 4 displays debug info and
+level 5 displays absolutely everything, including the nasty details of sends and
+receives. The -f switch allows output to be saved to a logfile.
+
+Security features: Please see the ptunnel man-page for instructions.
+
+
+Supported operating systems
+---------------------------
+Ptunnel supports most operating systems with libpcap, the usual POSIX functions
+and a BSD sockets compatible API. In particular, it has been tested on Linux
+Fedora Core 2 and Mac OS X 10.3.6 and above. As of version 0.7, ptunnel can also
+be compiled on Windows, courtesy of Mike Miller, assuming mingw and WinPcap is
+installed.
+
+
+Credits and contributors
+------------------------
+Thanks to L. Peter Deutsch for his open-source MD5 implementation, included with
+ptunnel, but also available here:
+http://sourceforge.net/projects/libmd5-rfc/
+
+Many thanks also to Mike Miller <mike@mikeage.net> for his work on creating a
+Windows port of ptunnel.
+
+Thanks to Sebastien Raveau <sebastien.raveau@epita.fr> for implementing various
+security features and SELinux support.
+
+Also thanks to Joe McKenzie, Steffen Wendzel and StalkR for contributing patches to
+ptunnel.
+
+License
+-------
+Ping Tunnel is Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
+Yellow Lemon Software. All rights reserved. Ping Tunnel is licensed under the
+BSD License. Please see the LICENSE file for details.
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..9a7d5a3
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,80 @@
+ptunnel (0.72-1) unstable; urgency=medium
+
+ * QA upload.
+ * New upstream release. Closes: #685305
+ * Switch to dpkg-source 3.0 (quilt) format.
+ * debian/copyright:
+ + Rewrite following copyright-format 1.0.
+ * debian/control
+ + Set QA team as Maintainer.
+ + Change debhelper to 9 in B-D.
+ + Bump Standards-Version to 3.9.7
+ + Remove cbds and quilt from B-D.
+ + Use dpkg architecture wildcards. Closes: #634477
+ * debian/compat
+ + Switch compat level 7 to 9.
+ * Use wrap-and-sort.
+ * Remove control.in file.
+ * Remove dirs file.
+ * Rename docs file to ptunnel.docs.
+ + Install only useful files: index.html,
+ packet-format.png, setup.png
+ * debian/patches
+ + Add add_hardening_flags.diff
+ + Set correctly hardening flags.
+ + Add DEP-3 header to fix_minux_chars_in_man.patch
+ + Add fix_typo.diff to fix typo error in README. Closes: #597288
+ + Rename makefile-debian-prefix to makefile-debian-prefix.patch
+ + Add DEP-3 header to makefile-debian-prefix.patch
+ * Add ptunnel.doc-base file.
+ * debian/rules
+ + Use Hardening flags.
+ * Update watch file.
+
+ -- Daniel Echeverry <epsilon77@gmail.com> Sat, 13 Feb 2016 20:49:23 -0500
+
+ptunnel (0.71-2) unstable; urgency=low
+
+ * Updated build-dep to allow building
+ in non-linux port. Thanks to Cyril Brulebois
+ for reporting the issue.
+ Closes: #559717
+ * Bumped standards-version to 3.8.3
+ * Added Homepage:
+
+ -- Romain Beauxis <toots@rastageeks.org> Wed, 09 Dec 2009 10:29:11 -0600
+
+ptunnel (0.71-1) unstable; urgency=low
+
+ * New upstream release.
+ * Updated standards to 3.8.2
+ * Bumped compat to 7
+ * Refreshed patches.
+ * Added build-dep on libselinux1-dev to enable SELinux support.
+
+ -- Romain Beauxis <toots@rastageeks.org> Thu, 30 Jul 2009 04:57:07 +0200
+
+ptunnel (0.70-1) unstable; urgency=low
+
+ * New upstream release
+ * Updated standards to 3.8.0
+ * Reverted build-deps on libpcap
+ * Updated debian/copyright
+
+ -- Romain Beauxis <toots@rastageeks.org> Wed, 25 Feb 2009 03:06:53 +0100
+
+ptunnel (0.61-2) unstable; urgency=low
+
+ * Wrapped description to 70th col (Closes: #325809)
+ * Switched to cdbs
+ * Updated debian standards
+ * Added patch to correct the manual page
+
+ -- Romain Beauxis <toots@rastageeks.org> Sun, 18 Feb 2007 13:39:47 +0100
+
+ptunnel (0.61-1) unstable; urgency=low
+
+ * Initial release Closes: #311348
+
+ -- Romain Beauxis <toots@rastageeks.org> Tue, 31 May 2005 20:49:25 +0200
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..f6cbedc
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,22 @@
+Source: ptunnel
+Section: net
+Priority: optional
+Maintainer: Debian QA Group <packages@qa.debian.org>
+Build-Depends: debhelper (>= 9),
+ libpcap0.8-dev | libpcap-dev,
+ libselinux1-dev [linux-any],
+ patchutils (>= 0.2.25)
+Standards-Version: 3.9.7
+Homepage: http://www.cs.uit.no/~daniels/PingTunnel/
+
+Package: ptunnel
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Tunnel TCP connections over ICMP packets
+ ptunnel is an application that allows you to reliably tunnel TCP
+ connections to a remote host using ICMP echo request and reply
+ packets, commonly known as ping requests and replies. It acts as
+ a proxy and can handle sockets and secured identification.
+ .
+ Those features can be very handy when working in a closed networking
+ environment with firewalls and proxies.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..042b79e
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,58 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: ptunnel
+Source: http://www.cs.uit.no/~daniels/PingTunnel/index.html
+
+Files: *
+Copyright: Copyright 2004-2011 Daniel Stoedle <daniels@cs.uit.no>, Yellow Lemon Software
+License: BSD-3-Clause
+
+Files: md5.*
+Copyright: Copyright 1999, 2000, 2002 Aladdin Enterprises
+License: Zlib
+
+Files: debian/*
+Copyright: 2005-2009 Romain Beauxis <toots@rastageeks.org>
+ 2016 Daniel Echeverry <epsilon77@gmail.com>
+License: BSD-3-Clause
+
+License: BSD-3-Clause
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ .
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+ .
+ 3. Neither the name of the copyright holder nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+License: Zlib
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+ .
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+ .
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
diff --git a/debian/patches/add_hardening_flags.diff b/debian/patches/add_hardening_flags.diff
new file mode 100644
index 0000000..b5ad8ba
--- /dev/null
+++ b/debian/patches/add_hardening_flags.diff
@@ -0,0 +1,28 @@
+Description: Add Hardening flags
+Forwarded: no
+Author: Daniel Echeverry <epsilon77@gmail.com>
+Last-Update: 2016-02-16
+--- a/Makefile
++++ b/Makefile
+@@ -32,7 +32,7 @@ install: ptunnel
+ install ./ptunnel.8 $(mandir)/ptunnel.8
+
+ ptunnel: $(PT_OBJS)
+- $(CC) -o $@ $^ $(LDOPTS) `[ -e /usr/include/selinux/selinux.h ] && echo -lselinux`
++ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS) `[ -e /usr/include/selinux/selinux.h ] && echo -lselinux`
+
+ ptunnel.exe: $(WIN32_PT_OBJS)
+ $(CC) -o $@ $^ $(WIN32_LDOPTS)
+@@ -44,10 +44,10 @@ clean:
+
+ depend: .depend
+ .depend:
+- $(CC) $(CFLAGS) -MM *.c > $@
++ $(CC) $(CFLAGS) $(CPPFLAGS) -MM *.c > $@
+
+ %.o:%.c
+- $(CC) $(CFLAGS) `[ -e /usr/include/selinux/selinux.h ] && echo -DHAVE_SELINUX` -c -o $@ $<
++ $(CC) $(CFLAGS) $(CPPFLAGS) `[ -e /usr/include/selinux/selinux.h ] && echo -DHAVE_SELINUX` -c -o $@ $<
+
+ %.obj:%.c
+ $(WIN32_CC) $(WIN32_CFLAGS) -c -o $@ $<
diff --git a/debian/patches/fix_minus_chars_in_man.patch b/debian/patches/fix_minus_chars_in_man.patch
new file mode 100644
index 0000000..f5ad5ac
--- /dev/null
+++ b/debian/patches/fix_minus_chars_in_man.patch
@@ -0,0 +1,72 @@
+Description: Fix hyphen-used-as-minus-sign lintian warning in manpage
+Forwarded: no
+Author: Romain Beauxis <toots@rastageeks.org>
+Last-Update: 2016-02-13
+--- a/ptunnel.8
++++ b/ptunnel.8
+@@ -3,7 +3,7 @@
+ ptunnel \- tunnel TCP connections over ICMP echo request/reply packets.
+ .SH SYNOPSIS
+ .B ptunnel
+-\-p proxy_address \-lp listen_port \-da destination_address \-dp dest_port [\-c network_device] [\-v verbosity] [-f file] [-udp] [-syslog]
++\-p proxy_address \-lp listen_port \-da destination_address \-dp dest_port [\-c network_device] [\-v verbosity] [\-f file] [\-udp] [\-syslog]
+
+ .B ptunnel
+ [\-c network_device] [\-v verbosity] [\-f file] [\-udp] [\-syslog] [\-daemon file]
+@@ -39,13 +39,13 @@ Specifies/restrict the port that the pro
+ Specify the network interface to capture packets from. Note that packet capturing isn't always necessary, but you should try this if you experience problems with ptunnel.
+ .TP
+ .B \-v verbosity
+-Controls the verbosity level. -1 is no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives.
++Controls the verbosity level. \-1 is no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives.
+ .TP
+ .B \-udp
+-Enables tunneling over UDP port 53 (DNS) instead of using ICMP. This will only work if your proxy can accept incoming traffic on port 53, and the client is able to send data to the proxy on port 53. Note that this option does not wrap ptunnel's data in DNS-compliant packets. This option must be given on both the proxy and client side for things to work correctly.
++Enables tunneling over UDP port 53 (DNS) instead of using ICMP. This will only work if your proxy can accept incoming traffic on port 53, and the client is able to send data to the proxy on port 53. Note that this option does not wrap ptunnel's data in DNS\-compliant packets. This option must be given on both the proxy and client side for things to work correctly.
+ .TP
+ .B \-syslog (Not available on Windows.)
+-Changes logging to use the built-in syslog fascility.
++Changes logging to use the built\-in syslog fascility.
+ .TP
+ .B \-daemon file (Not available on Windows.)
+ Run in background, writing PID in file.
+@@ -64,13 +64,13 @@ When started in privileged mode, restric
+ .TP
+ .B \-setcon context (Not available on Windows.)
+ Set SELinux context when all there is left to do are network I/O operations.
+-In order to be able to combine with -chroot you will have to `mount --bind /proc /chrootdir/proc`
++In order to be able to combine with \-chroot you will have to `mount --bind /proc /chrootdir/proc`
+ .TP
+ .B \-x password
+ Specifies a password or passphrase to use. This will allow you to protect the proxy from use by others who don't know the password. It needs to be specified on both proxy and client.
+ .TP
+ .B \-f file
+-Specifies a log file. If you specify -syslog, syslog is always used instead.
++Specifies a log file. If you specify \-syslog, syslog is always used instead.
+ .TP
+ .B \-h
+ Displays brief usage information.
+@@ -84,19 +84,19 @@ An ssh connection to login.domain.com ca
+ .TP
+ .B ssh \-p 8000 localhost
+ .PP
+-If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts.
++If ssh complains about potential man\-in\-the\-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts.
+
+-Of course, for all of this to work, you need to start the proxy on your proxy-computer (proxy.pingtunnel.com). Doing this is very simple:
++Of course, for all of this to work, you need to start the proxy on your proxy\-computer (proxy.pingtunnel.com). Doing this is very simple:
+
+ .B ptunnel
+
+ If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -c switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On Mac OS X, packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise.
+
+-To protect yourself from others using your proxy, you can protect access to it with a password using the <tt>-x</tt> switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.
++To protect yourself from others using your proxy, you can protect access to it with a password using the <tt>\-x</tt> switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.
+
+ .SH EXIT STATUS
+ .B ptunnel
+-does not exit until forced to do so by an interrupt (Ctrl-C) or if it crashes.
++does not exit until forced to do so by an interrupt (Ctrl\-C) or if it crashes.
+ .SH BUGS
+ .B ptunnel
+ currently does not handle packet capturing on network interfaces other than ethernet or wireless correctly.
diff --git a/debian/patches/fix_typo.diff b/debian/patches/fix_typo.diff
new file mode 100644
index 0000000..cb7ded8
--- /dev/null
+++ b/debian/patches/fix_typo.diff
@@ -0,0 +1,15 @@
+Description: Fix typo in README file
+Forwarded: no
+Author: Daniel Echeverry <epsilon77@gmail.com>
+Last-Update: 2016-02-14
+--- a/README
++++ b/README
+@@ -10,7 +10,7 @@ ping requests and replies.
+
+ Contact details
+ ---------------
+-You can the author, Daniel Stoedle, here:
++You can contact the author, Daniel Stoedle, here:
+ <daniels@cs.uit.no>
+ The official ptunnel website is located here:
+ <http://www.cs.uit.no/~daniels/PingTunnel/>
diff --git a/debian/patches/makefile-debian-prefix.patch b/debian/patches/makefile-debian-prefix.patch
new file mode 100644
index 0000000..60b36d5
--- /dev/null
+++ b/debian/patches/makefile-debian-prefix.patch
@@ -0,0 +1,17 @@
+Description: Set debian paths
+Forwarded: no
+Author: Romain Beauxis <toots@rastageeks.org>
+Last-Update: 2016-02-13
+--- a/Makefile
++++ b/Makefile
+@@ -12,8 +12,8 @@ WIN32_CFLAGS = -g -Wall -DWIN32 -I"c:\Pr
+ WIN32_LDOPTS = -lwpcap -lwsock32 -L"c:\Program Files\WpdPack\Lib"
+ WIN32_PT_OBJS = ptunnel.obj md5.obj
+
+-prefix = /usr
+-bindir = $(prefix)/bin
++prefix = $(DESTDIR)/usr
++bindir = $(prefix)/sbin
+ mandir = $(prefix)/share/man/man8
+
+ all: ptunnel
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..9a8f77a
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,4 @@
+add_hardening_flags.diff
+fix_typo.diff
+fix_minus_chars_in_man.patch
+makefile-debian-prefix.patch
diff --git a/debian/ptunnel.doc-base b/debian/ptunnel.doc-base
new file mode 100644
index 0000000..a332a7a
--- /dev/null
+++ b/debian/ptunnel.doc-base
@@ -0,0 +1,10 @@
+Document: ptunnel
+Title: Debian ptunnel manual
+Author: Daniel Stoedle <daniels@cs.uit.no>
+Abstract: This manual describes how works ptunnel and how use it.
+Section: Network/Communication
+
+Format: HTML
+Index: /usr/share/doc/ptunnel/index.html
+Files: /usr/share/doc/ptunnel/index.html
+
diff --git a/debian/ptunnel.docs b/debian/ptunnel.docs
new file mode 100644
index 0000000..6a5af59
--- /dev/null
+++ b/debian/ptunnel.docs
@@ -0,0 +1,4 @@
+README
+web/index.html
+web/packet-format.png
+web/setup.png
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..896d652
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,11 @@
+#!/usr/bin/make -f
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
+CFLAGS:=$(shell dpkg-buildflags --get CFLAGS)
+LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
+
+%:
+ dh $@
+
+override_dh_auto_build:
+ dh_auto_build -- CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)"
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..71b0b4f
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,5 @@
+version=3
+http://www.cs.uit.no/~daniels/PingTunnel/PingTunnel-(.*)\.tar\.gz
+
+
+
diff --git a/md5.c b/md5.c
new file mode 100755
index 0000000..cd87d02
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,381 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.1 2005/04/15 07:37:22 daniels Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/md5.h b/md5.h
new file mode 100755
index 0000000..e2804fe
--- /dev/null
+++ b/md5.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.1 2005/04/15 07:37:22 daniels Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/ptunnel.8 b/ptunnel.8
new file mode 100755
index 0000000..2377b2f
--- /dev/null
+++ b/ptunnel.8
@@ -0,0 +1,123 @@
+.TH ptunnel 8 "September 5, 2011" "Version 0.72" "Yellow Lemon Software"
+.SH NAME
+ptunnel \- tunnel TCP connections over ICMP echo request/reply packets.
+.SH SYNOPSIS
+.B ptunnel
+\-p proxy_address \-lp listen_port \-da destination_address \-dp dest_port [\-c network_device] [\-v verbosity] [\-f file] [\-udp] [\-syslog]
+
+.B ptunnel
+[\-c network_device] [\-v verbosity] [\-f file] [\-udp] [\-syslog] [\-daemon file]
+
+.B ptunnel
+[\-u] [\-x password] [\-setuid user] [\-setgid group] [\-chroot dir] [\-setcon context]
+
+.B ptunnel
+\-h
+.SH DESCRIPTION
+ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. At first glance, this might seem like a rather useless thing to do, but it can actually come in handy in some cases. The following example illustrates the main motivation in creating ptunnel:
+.PP
+Setting: You're on the go, and stumble across an open wireless network. The network gives you an IP address, but won't let you send TCP or UDP packets out to the rest of the internet, for instance to check your mail. What to do? By chance, you discover that the network will allow you to ping any computer on the rest of the internet. With ptunnel, you can utilize this feature to check your mail, or do other things that require TCP.
+.SH OPTIONS
+.TP
+.SH Client options:
+.TP
+.B \-p proxy_address
+Specify the host on which the proxy is running.
+.TP
+.B \-lp listen_port
+Specifies the port on which the client will listen for incoming TCP connections.
+.TP
+.B \-da destination_addr
+Specifies the address to which you want your packets tunneled after reaching the proxy when in client mode, or restricts the destination packets can be forwarded to when in server mode.
+.TP
+.B \-dp destination_port
+Specifies/restrict the port that the proxy should tunnel the TCP connection to.
+.TP
+.SH Shared options:
+.TP
+.B \-c network_device
+Specify the network interface to capture packets from. Note that packet capturing isn't always necessary, but you should try this if you experience problems with ptunnel.
+.TP
+.B \-v verbosity
+Controls the verbosity level. \-1 is no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives.
+.TP
+.B \-udp
+Enables tunneling over UDP port 53 (DNS) instead of using ICMP. This will only work if your proxy can accept incoming traffic on port 53, and the client is able to send data to the proxy on port 53. Note that this option does not wrap ptunnel's data in DNS\-compliant packets. This option must be given on both the proxy and client side for things to work correctly.
+.TP
+.B \-syslog (Not available on Windows.)
+Changes logging to use the built\-in syslog fascility.
+.TP
+.B \-daemon file (Not available on Windows.)
+Run in background, writing PID in file.
+.TP
+.B \-u
+Attempts to run ptunnel without privileges. This doesn't usually work! On UNIX systems please consider using the following three options instead:
+.TP
+.B \-setuid user (Not available on Windows.)
+When started in privileged mode, drop down to user's rights as soon as possible.
+.TP
+.B \-setgid group (Not available on Windows.)
+When started in privileged mode, drop down to group's rights as soon as possible.
+.TP
+.B \-chroot dir (Not available on Windows.)
+When started in privileged mode, restrict file access to the specified directory.
+.TP
+.B \-setcon context (Not available on Windows.)
+Set SELinux context when all there is left to do are network I/O operations.
+In order to be able to combine with \-chroot you will have to `mount --bind /proc /chrootdir/proc`
+.TP
+.B \-x password
+Specifies a password or passphrase to use. This will allow you to protect the proxy from use by others who don't know the password. It needs to be specified on both proxy and client.
+.TP
+.B \-f file
+Specifies a log file. If you specify \-syslog, syslog is always used instead.
+.TP
+.B \-h
+Displays brief usage information.
+
+.SH EXAMPLES
+The following assumes that ptunnel is run as root, both on the proxy and client. To tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used:
+.TP
+.B ptunnel \-p proxy.pingtunnel.com \-lp 8000 \-da login.domain.com \-dp 22
+.PP
+An ssh connection to login.domain.com can now be established as follows:
+.TP
+.B ssh \-p 8000 localhost
+.PP
+If ssh complains about potential man\-in\-the\-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts.
+
+Of course, for all of this to work, you need to start the proxy on your proxy\-computer (proxy.pingtunnel.com). Doing this is very simple:
+
+.B ptunnel
+
+If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -c switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On Mac OS X, packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise.
+
+To protect yourself from others using your proxy, you can protect access to it with a password using the <tt>\-x</tt> switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.
+
+.SH EXIT STATUS
+.B ptunnel
+does not exit until forced to do so by an interrupt (Ctrl\-C) or if it crashes.
+.SH BUGS
+.B ptunnel
+currently does not handle packet capturing on network interfaces other than ethernet or wireless correctly.
+.SH AUTHORS AND CONTRIBUTORS
+Daniel Stoedle (daniels@cs.uit.no)
+
+Windows port: Mike Miller (mike@mikeage.net)
+
+SELinux support: Sebastien Raveau (sebastien.raveau@epita.fr)
+
+Patches: Joe McKenzie, Steffen Wendzel and StalkR.
+
+.SH LICENSE
+.B ptunnel
+is licensed under the BSD License.
+.SH AVAILABILITY
+.TP
+The ptunnel homepage is currently located here:
+http://www.cs.uit.no/~daniels/PingTunnel/
+.TP
+The freshmeat project page is located here:
+http://freshmeat.net/projects/ptunnel/
+.PP
+Please take the time to rate ptunnel if you find it useful. Thanks!
diff --git a/ptunnel.c b/ptunnel.c
new file mode 100755
index 0000000..cd8dcd5
--- /dev/null
+++ b/ptunnel.c
@@ -0,0 +1,1622 @@
+/* ptunnel.c
+ ptunnel is licensed under the BSD license:
+
+ Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
+ Yellow Lemon Software. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of the Yellow Lemon Software nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Contacting the author:
+ You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe,
+ in case your text editor didn't realize), here: <daniels@cs.uit.no>
+
+ The official ptunnel website is here:
+ <http://www.cs.uit.no/~daniels/PingTunnel/>
+
+ Note that the source code is best viewed with tabs set to 4 spaces.
+*/
+
+#include "ptunnel.h"
+#include "md5.h"
+
+#ifdef WIN32
+ /* pthread porting to windows */
+ typedef CRITICAL_SECTION pthread_mutex_t;
+ typedef unsigned long pthread_t;
+ #define pthread_mutex_init InitializeCriticalSectionAndSpinCount
+ #define pthread_mutex_lock EnterCriticalSection
+ #define pthread_mutex_unlock LeaveCriticalSection
+
+ #include <winsock2.h>
+ /* Map errno (which Winsock doesn't use) to GetLastError; include the code in the strerror */
+ #ifdef errno
+ #undef errno
+ #endif /* errno */
+ #define errno GetLastError()
+ /* Local error string storage */
+ static char errorstr[255];
+ static char * print_last_windows_error() {
+ DWORD last_error = GetLastError();
+ memset(errorstr, 0, sizeof(errorstr));
+ FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, 0, errorstr, sizeof(errorstr), NULL);
+ snprintf(errorstr, sizeof(errorstr), "%s (%d)", errorstr, last_error);
+ return errorstr;
+ }
+ #define strerror(x) print_last_windows_error()
+#else
+#ifdef HAVE_SELINUX
+ #include <selinux/selinux.h>
+ static char *selinux_context = NULL;
+#endif
+ static uid_t uid = 0;
+ static gid_t gid = 0;
+ static char *root_dir = NULL;
+ static bool daemonize = false;
+ static FILE *pid_file = NULL;
+#endif /* WIN32 */
+
+
+// Lots of globals
+pthread_mutex_t chain_lock, // Lock protecting the chain of connections
+ num_threads_lock; // Lock protecting the num_threads variable
+
+bool unprivileged = false, // True if user wants to run without root
+ pcap = false, // True if user wants packet capturing
+ print_stats = false, // True if user wants continuous statistics printed.
+ use_syslog = false; // True if user wants to log to syslog
+FILE *log_file = 0; // Usually stdout, but can be altered by the user
+
+int tcp_port = -1, // Port to send data to from the proxy
+ tcp_listen_port = -1, // Port the client listens on
+ log_level = kLog_event, // Default log level
+ mode = kMode_proxy, // Default mode (proxy)
+ num_threads = 0, // Current thread count
+ max_tunnels = kMax_tunnels, // Default maximum number of tunnels to support at once
+ num_tunnels = 0, // Current tunnel count
+ use_udp = 0; // True if UDP should be used for transport (proxy runs on port 53)
+uint32_t *seq_expiry_tbl = 0, // Table indicating when a connection ID is allowable (used by proxy)
+ given_proxy_ip = 0, // Proxy's internet address
+ given_dst_ip = 0; // Destination client wants data forwarded to
+char *password = 0, // Password (must be the same on proxy and client for authentication to succeed)
+ password_digest[kMD5_digest_size], // MD5 digest of password
+ *pcap_device = 0; // Device to capture packets from
+
+// Some buffer constants
+const int tcp_receive_buf_len = kDefault_buf_size,
+ icmp_receive_buf_len = kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t),
+ pcap_buf_size = (kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t)+64)*64;
+char pcap_filter_program[] = "icmp"; // && (icmp[icmptype] = icmp-echo || icmp[icmptype] = icmp-echoreply)";
+
+// The chain of client/proxy connections
+proxy_desc_t *chain = 0;
+const char *state_name[kNum_proto_types] = { "start", "ack", "data", "close", "authenticate" };
+
+// Let the fun begin!
+int main(int argc, char *argv[]) {
+ int i, opt;
+ md5_state_t state;
+ struct hostent *host_ent;
+#ifndef WIN32
+ struct passwd *pwnam;
+ struct group *grnam;
+ pid_t pid;
+#endif
+#ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ return -1;
+ }
+
+ if ( LOBYTE( wsaData.wVersion ) != 2 ||
+ HIBYTE( wsaData.wVersion ) != 2 ) {
+ WSACleanup();
+ return -1;
+ }
+#endif /* WIN32 */
+
+
+ // Seed random generator; it'll be used in combination with a timestamp
+ // when generating authentication challenges.
+ srand(time(0));
+ memset(password_digest, 0, kMD5_digest_size);
+
+ /* The seq_expiry_tbl is used to prevent the remote ends from prematurely
+ re-using a sequence number.
+ */
+ seq_expiry_tbl = calloc(65536, sizeof(uint32_t));
+
+ log_file = stdout;
+
+ // Parse options
+ opt = kOpt_undefined;
+ mode = kMode_proxy;
+ for (i=1;i<argc;i++) {
+ if (strcmp(argv[i], "-p") == 0) {
+ mode = kMode_forward;
+ opt = kOpt_set_proxy_addr;
+ }
+ else if (strcmp(argv[i], "-x") == 0)
+ opt = kOpt_set_password;
+ else if (strcmp(argv[i], "-lp") == 0)
+ opt = kOpt_set_tcp_port;
+ else if (strcmp(argv[i], "-da") == 0)
+ opt = kOpt_set_tcp_dest_addr;
+ else if (strcmp(argv[i], "-dp") == 0)
+ opt = kOpt_set_tcp_dest_port;
+ else if (strcmp(argv[i], "-v") == 0)
+ opt = kOpt_set_verbosity;
+ else if (strcmp(argv[i], "-m") == 0)
+ opt = kOpt_set_max_tunnels;
+ else if (strcmp(argv[i], "-u") == 0)
+ unprivileged = !unprivileged;
+ else if (strcmp(argv[i], "-c") == 0)
+ opt = kOpt_set_pcap_device;
+ else if (strcmp(argv[i], "-f") == 0)
+ opt = kOpt_set_log_file;
+ else if (strcmp(argv[i], "-s") == 0)
+ print_stats = !print_stats;
+ #ifndef WIN32
+ else if (strcmp(argv[i], "-syslog") == 0)
+ use_syslog = !use_syslog;
+ else if (strcmp(argv[i], "-setuid") == 0)
+ opt = kOpt_set_unpriv_user;
+ else if (strcmp(argv[i], "-setgid") == 0)
+ opt = kOpt_set_unpriv_group;
+ else if (strcmp(argv[i], "-chroot") == 0)
+ opt = kOpt_set_root_dir;
+ else if (strcmp(argv[i], "-setcon") == 0)
+ opt = kOpt_set_selinux_context;
+ else if (strcmp(argv[i], "-daemon") == 0)
+ opt = kOpt_daemonize;
+ #endif /* !WIN32 */
+ else if (strcmp(argv[i], "-udp") == 0)
+ use_udp = 1;
+ else {
+ switch (opt) {
+ case kOpt_set_proxy_addr:
+ if (NULL == (host_ent = gethostbyname(argv[i]))) {
+ pt_log(kLog_error, "Failed to look up %s as proxy address\n", argv[i]);
+ return 1;
+ }
+ given_proxy_ip = *(uint32_t*)host_ent->h_addr_list[0];
+ break;
+ case kOpt_set_password:
+ password = argv[i];
+ pt_log(kLog_debug, "Password set - unauthenicated connections will be refused.\n");
+ // Compute the password digest
+ md5_init(&state);
+ md5_append(&state, (md5_byte_t*)password, strlen(password));
+ md5_finish(&state, (md5_byte_t*)password_digest);
+ // Hide the password in process listing
+ memset(argv[i], ' ', strlen(argv[i]));
+ break;
+ case kOpt_set_tcp_port:
+ tcp_listen_port = atoi(argv[i]);
+ break;
+ case kOpt_set_tcp_dest_addr:
+ if (NULL == (host_ent = gethostbyname(argv[i]))) {
+ pt_log(kLog_error, "Failed to look up %s as destination address\n", argv[i]);
+ return 1;
+ }
+ given_dst_ip = *(uint32_t*)host_ent->h_addr_list[0];
+ break;
+ case kOpt_set_tcp_dest_port:
+ tcp_port = atoi(argv[i]);
+ break;
+ case kOpt_set_max_tunnels:
+ max_tunnels = atoi(argv[i]);
+ if (max_tunnels <= 0)
+ max_tunnels = kMax_tunnels;
+ break;
+ case kOpt_set_verbosity:
+ log_level = atoi(argv[i]);
+ break;
+ case kOpt_set_pcap_device:
+ pcap_device = argv[i];
+ pcap = 1;
+ break;
+ case kOpt_set_log_file:
+ log_file = fopen(argv[i], "a");
+ if (!log_file) {
+ log_file = stdout;
+ pt_log(kLog_error, "Failed to open log file: '%s'. Cause: %s\n", argv[i], strerror(errno));
+ pt_log(kLog_error, "Reverting log to standard out.\n");
+ }
+ break;
+ #ifndef WIN32
+ case kOpt_set_unpriv_user:
+ errno = 0;
+ if (NULL == (pwnam = getpwnam(argv[i]))) {
+ pt_log(kLog_error, "%s: %s\n", argv[i], errno ? strerror(errno) : "unknown user");
+ exit(1);
+ }
+ uid = pwnam->pw_uid;
+ if (!gid)
+ gid = pwnam->pw_gid;
+ break;
+ case kOpt_set_unpriv_group:
+ errno = 0;
+ if (NULL == (grnam = getgrnam(argv[i]))) {
+ pt_log(kLog_error, "%s: %s\n", argv[i], errno ? strerror(errno) : "unknown group");
+ exit(1);
+ }
+ gid = grnam->gr_gid;
+ break;
+ case kOpt_set_root_dir:
+ root_dir = strdup(argv[i]);
+ break;
+ case kOpt_set_selinux_context:
+ #ifdef HAVE_SELINUX
+ selinux_context = strdup(argv[i]);
+ #else
+ pt_log(kLog_error, "Sorry: SELinux support missing, please recompile with libselinux.\n");
+ return 1;
+ #endif
+ break;
+ case kOpt_daemonize:
+ daemonize = true;
+ if (NULL == (pid_file = fopen(argv[i], "w")))
+ pt_log(kLog_error, "%s: %s\n", argv[i], strerror(errno));
+ break;
+ #endif /* !WIN32 */
+ case kOpt_undefined:
+ usage(argv[0]);
+ return 1;
+ }
+ opt = kOpt_undefined;
+ }
+ }
+ if (opt != kOpt_undefined) {
+ usage(argv[0]);
+ exit(1);
+ }
+ if (pcap && use_udp) {
+ pt_log(kLog_error, "Packet capture is not supported (or needed) when using UDP for transport.\n");
+ pcap = 0;
+ }
+ pt_log(kLog_info, "Starting ptunnel v %d.%.2d.\n", kMajor_version, kMinor_version);
+ pt_log(kLog_info, "(c) 2004-2011 Daniel Stoedle, <daniels@cs.uit.no>\n");
+ #ifdef WIN32
+ pt_log(kLog_info, "Windows version by Mike Miller, <mike@mikeage.net>\n");
+ #else
+ pt_log(kLog_info, "Security features by Sebastien Raveau, <sebastien.raveau@epita.fr>\n");
+ #endif
+ pt_log(kLog_info, "%s.\n", (mode == kMode_forward ? "Relaying packets from incoming TCP streams" : "Forwarding incoming ping packets over TCP"));
+ if (use_udp)
+ pt_log(kLog_info, "UDP transport enabled.\n");
+
+#ifndef WIN32
+ signal(SIGPIPE, SIG_IGN);
+ if (use_syslog) {
+ if (log_file != stdout) {
+ pt_log(kLog_error, "Logging using syslog overrides the use of a specified logfile (using -f).\n");
+ fclose(log_file);
+ log_file = stdout;
+ }
+ openlog("ptunnel", LOG_PID, LOG_USER);
+ }
+ if (NULL != root_dir) {
+ pt_log(kLog_info, "Restricting file access to %s\n", root_dir);
+ if (-1 == chdir(root_dir) || -1 == chroot(root_dir)) {
+ pt_log(kLog_error, "%s: %s\n", root_dir, strerror(errno));
+ exit(1);
+ }
+ }
+ if (daemonize) {
+ pt_log(kLog_info, "Going to the background.\n");
+ if (0 < (pid = fork()))
+ exit(0);
+ if (0 > pid)
+ pt_log(kLog_error, "fork: %s\n", strerror(errno));
+ else
+ if (-1 == setsid())
+ pt_log(kLog_error, "setsid: %s\n", strerror(errno));
+ else {
+ if (0 < (pid = fork()))
+ exit(0);
+ if (0 > pid)
+ pt_log(kLog_error, "fork: %s\n", strerror(errno));
+ else {
+ if (NULL != pid_file) {
+ fprintf(pid_file, "%d\n", getpid());
+ fclose(pid_file);
+ }
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ }
+ }
+ }
+#endif /* !WIN32 */
+
+#ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ return -1;
+ }
+
+ if ( LOBYTE( wsaData.wVersion ) != 2 ||
+ HIBYTE( wsaData.wVersion ) != 2 ) {
+ WSACleanup();
+ return -1;
+ }
+#endif /* WIN32 */
+ pthread_mutex_init(&chain_lock, 0);
+ pthread_mutex_init(&num_threads_lock, 0);
+
+ // Check mode, validate arguments and start either client or proxy.
+ if (mode == kMode_forward) {
+ if (!given_proxy_ip || !given_dst_ip || !tcp_port || !tcp_listen_port) {
+ printf("One of the options are missing or invalid.\n");
+ usage(argv[0]);
+ return -1;
+ }
+ pt_forwarder();
+ }
+ else
+ pt_proxy(0);
+
+ // Clean up
+ if (log_file != stdout)
+ fclose(log_file);
+
+#ifdef WIN32
+ WSACleanup();
+#else
+ if (NULL != root_dir)
+ free(root_dir);
+ #ifdef HAVE_SELINUX
+ if (NULL != selinux_context)
+ free(selinux_context);
+ #endif
+#endif /* WIN32 */
+
+ pt_log(kLog_info, "ptunnel is exiting.\n");
+ return 0;
+}
+
+
+void usage(char *exec_name) {
+ printf("ptunnel v %d.%.2d.\n", kMajor_version, kMinor_version);
+ printf("Usage: %s -p <addr> -lp <port> -da <dest_addr> -dp <dest_port> [-m max_tunnels] [-v verbosity] [-f logfile]\n", exec_name);
+ printf(" %s [-m max_threads] [-v verbosity] [-c <device>]\n", exec_name);
+ printf(" -p: Set address of peer running packet forwarder. This causes\n");
+ printf(" ptunnel to operate in forwarding mode - the absence of this\n");
+ printf(" option causes ptunnel to operate in proxy mode.\n");
+ printf(" -lp: Set TCP listening port (only used when operating in forward mode)\n");
+ printf(" -da: Set remote proxy destination address if client\n");
+ printf(" Restrict to only this destination address if server\n");
+ printf(" -dp: Set remote proxy destionation port if client\n");
+ printf(" Restrict to only this destination port if server\n");
+ printf(" -m: Set maximum number of concurrent tunnels\n");
+ printf(" -v: Verbosity level (-1 to 4, where -1 is no output, and 4 is all output)\n");
+ printf(" -c: Enable libpcap on the given device.\n");
+ printf(" -f: Specify a file to log to, rather than printing to standard out.\n");
+ printf(" -s: Client only. Enables continuous output of statistics (packet loss, etc.)\n");
+ #ifndef WIN32
+ printf("-daemon: Run in background, the PID will be written in the file supplied as argument\n");
+ printf("-syslog: Output debug to syslog instead of standard out.\n");
+ #endif /* !WIN32 */
+ printf(" -udp: Toggle use of UDP instead of ICMP. Proxy will listen on port 53 (must be root).\n\n");
+
+ printf("Security features: [-x password] [-u] [-setuid user] [-setgid group] [-chroot dir]\n");
+ printf(" -x: Set password (must be same on client and proxy)\n");
+ printf(" -u: Run proxy in unprivileged mode. This causes the proxy to forward\n");
+ printf(" packets using standard echo requests, instead of crafting custom echo replies.\n");
+ printf(" Unprivileged mode will only work on some systems, and is in general less reliable\n");
+ printf(" than running in privileged mode.\n");
+ #ifndef WIN32
+ printf(" Please consider combining the following three options instead:\n");
+ printf("-setuid: When started in privileged mode, drop down to user's rights as soon as possible\n");
+ printf("-setgid: When started in privileged mode, drop down to group's rights as soon as possible\n");
+ printf("-chroot: When started in privileged mode, restrict file access to the specified directory\n");
+ printf("-setcon: Set SELinux context when all there is left to do are network I/O operations\n");
+ printf(" To combine with -chroot you will have to `mount --bind /proc /chrootdir/proc`\n");
+ #endif /* !WIN32 */
+
+ printf("\nStarting the proxy (needs to run as root):\n");
+ printf(" [root #] %s\n", exec_name);
+ printf("Starting a client (also needs root):\n");
+ printf(" [root #] %s -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22 -c eth0\n", exec_name);
+ printf("And then using the tunnel to ssh to login.domain.com:\n");
+ printf(" [user $] ssh -p 8000 localhost\n");
+ printf("And that's it. Enjoy your tunnel!\n\n");
+}
+
+
+/* pt_forwarder:
+ Sets up a listening TCP socket, and forwards incoming connections
+ over ping packets.
+*/
+void pt_forwarder(void) {
+ int server_sock, new_sock, sock, yes = 1;
+ fd_set set;
+ struct timeval time;
+ struct sockaddr_in addr, dest_addr;
+ socklen_t addr_len;
+ pthread_t pid;
+ uint16_t rand_id;
+
+ pt_log(kLog_debug, "Starting forwarder..\n");
+ // Open our listening socket
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(int)) == -1) {
+ pt_log(kLog_error, "Failed to set SO_REUSEADDR option on listening socket: %s\n", strerror(errno));
+ close(sock);
+ return;
+ }
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(tcp_listen_port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+ memset(&(addr.sin_zero), 0, 8);
+ if (bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1) {
+ pt_log(kLog_error, "Failed to bind listening socket: %s\n", strerror(errno));
+ close(sock);
+ return;
+ }
+ server_sock = sock;
+ // Fill out address structure
+ memset(&dest_addr, 0, sizeof(struct sockaddr_in));
+ dest_addr.sin_family = AF_INET;
+ if (use_udp)
+ dest_addr.sin_port = htons(kDNS_port /* dns port.. */);
+ else
+ dest_addr.sin_port = 0;
+ dest_addr.sin_addr.s_addr = given_proxy_ip;
+ pt_log(kLog_verbose, "Proxy IP address: %s\n", inet_ntoa(*((struct in_addr*)&given_proxy_ip)));
+
+ listen(server_sock, 10);
+ while (1) {
+ FD_ZERO(&set);
+ FD_SET(server_sock, &set);
+ time.tv_sec = 1;
+ time.tv_usec = 0;
+ if (select(server_sock+1, &set, 0, 0, &time) > 0) {
+ pt_log(kLog_info, "Incoming connection.\n");
+ addr_len = sizeof(struct sockaddr_in);
+ new_sock = accept(server_sock, (struct sockaddr*)&addr, &addr_len);
+ if (new_sock < 0) {
+ pt_log(kLog_error, "Accepting incoming connection failed.\n");
+ continue;
+ }
+ pthread_mutex_lock(&num_threads_lock);
+ if (num_threads <= 0) {
+ pt_log(kLog_event, "No running proxy thread - starting it.\n");
+#ifndef WIN32
+ if (pthread_create(&pid, 0, pt_proxy, 0) != 0)
+#else
+ if (0 == (pid = _beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))pt_proxy, 0, 0, 0)))
+#endif
+ {
+ pt_log(kLog_error, "Couldn't create thread! Dropping incoming connection.\n");
+ close(new_sock);
+ pthread_mutex_unlock(&num_threads_lock);
+ continue;
+ }
+ }
+ addr = dest_addr;
+ rand_id = (uint16_t)rand();
+ create_and_insert_proxy_desc(rand_id, rand_id, new_sock, &addr, given_dst_ip, tcp_port, kProxy_start, kUser_flag);
+ pthread_mutex_unlock(&num_threads_lock);
+ }
+ }
+}
+
+
+int pt_create_udp_socket(int port) {
+ struct sockaddr_in addr;
+ int sock, yes = 1;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pt_log(kLog_error, "Failed to set create UDP socket..\n");
+ return 0;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void*)&yes, sizeof(int)) < 0) {
+ pt_log(kLog_error, "Failed to set UDP REUSEADDR socket option. (Not fatal, hopefully.)\n");
+ close(sock);
+ return 0;
+ }
+ #ifdef SO_REUSEPORT
+ yes = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const void*)&yes, sizeof(int)) < 0)
+ pt_log(kLog_error, "Failed to set UDP REUSEPORT socket option. (Not fatal, hopefully.)\n");
+ #endif //SO_REUSEPORT
+
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+ if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) < 0) {
+ pt_log(kLog_error, "Failed to bind UDP socket to port %d (try running as root).\n", port);
+ close(sock);
+ return 0;
+ }
+ return sock;
+}
+
+#define kPT_add_iphdr 0
+
+/* pt_proxy: This function does all the client and proxy stuff.
+*/
+void* pt_proxy(void *args) {
+ fd_set set;
+ struct timeval timeout;
+ int bytes;
+ struct sockaddr_in addr;
+ socklen_t addr_len;
+ int fwd_sock = 0,
+ max_sock = 0,
+ idx;
+ char *buf;
+ double now, last_status_update = 0.0;
+ proxy_desc_t *cur, *prev, *tmp;
+ pcap_info_t pc;
+ xfer_stats_t xfer;
+
+ // Start the thread, initialize protocol and ring states.
+ pt_log(kLog_debug, "Starting ping proxy..\n");
+ if (use_udp) {
+ pt_log(kLog_debug, "Creating UDP socket..\n");
+ if (mode == kMode_proxy)
+ fwd_sock = pt_create_udp_socket(kDNS_port);
+ else
+ fwd_sock = pt_create_udp_socket(0);
+ if (!fwd_sock) {
+ pt_log(kLog_error, "Failed to create UDP socket.\n");
+ return 0;
+ }
+ }
+ else {
+ if (unprivileged) {
+ pt_log(kLog_debug, "Attempting to create unprivileged ICMP datagram socket..\n");
+ fwd_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
+ }
+ else {
+ #if kPT_add_iphdr
+ int opt = 1;
+ #endif
+ pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n");
+ #if kPT_add_iphdr
+ // experimental
+ fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
+ printf("Set ip-hdr-inc; result = %d\n", setsockopt(fwd_sock, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt)));
+ #else
+ fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ #endif
+ }
+ if (fwd_sock < 0) {
+ pt_log(kLog_error, "Couldn't create %s socket: %s\n", (unprivileged ? "unprivileged datagram" : "privileged raw"), strerror(errno));
+ return 0;
+ }
+ }
+ max_sock = fwd_sock+1;
+ if (pcap) {
+ if (use_udp) {
+ pt_log(kLog_error, "Packet capture is not useful with UDP [should not get here!]!\n");
+ close(fwd_sock);
+ return 0;
+ }
+ if (!unprivileged) {
+ pt_log(kLog_info, "Initializing pcap.\n");
+ pc.pcap_err_buf = malloc(PCAP_ERRBUF_SIZE);
+ pc.pcap_data_buf = malloc(pcap_buf_size);
+ pc.pcap_desc = pcap_open_live(pcap_device, pcap_buf_size, 0 /* promiscous */, 50 /* ms */, pc.pcap_err_buf);
+ if (pc.pcap_desc) {
+ if (pcap_lookupnet(pcap_device, &pc.netp, &pc.netmask, pc.pcap_err_buf) == -1) {
+
+ pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
+ pcap = 0;
+ }
+ pt_log(kLog_verbose, "Network: %s\n", inet_ntoa(*(struct in_addr*)&pc.netp));
+ pt_log(kLog_verbose, "Netmask: %s\n", inet_ntoa(*(struct in_addr*)&pc.netmask));
+ if (pcap_compile(pc.pcap_desc, &pc.fp, pcap_filter_program, 0, pc.netp) == -1) {
+ pt_log(kLog_error, "Failed to compile pcap filter program.\n");
+ pcap_close(pc.pcap_desc);
+ pcap = 0;
+ }
+ else if (pcap_setfilter(pc.pcap_desc, &pc.fp) == -1) {
+ pt_log(kLog_error, "Failed to set pcap filter program.\n");
+ pcap_close(pc.pcap_desc);
+ pcap = 0;
+ }
+ }
+ else {
+ pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
+ pcap = 0;
+ }
+ pc.pkt_q.head = 0;
+ pc.pkt_q.tail = 0;
+ pc.pkt_q.elems = 0;
+ // Check if we have succeeded, and free stuff if not
+ if (!pcap) {
+ pt_log(kLog_error, "There were errors enabling pcap - pcap has been disabled.\n");
+ free(pc.pcap_err_buf);
+ free(pc.pcap_data_buf);
+ return 0;
+ }
+ }
+ else
+ pt_log(kLog_info, "pcap disabled since we're running in unprivileged mode.\n");
+ }
+
+ pthread_mutex_lock(&num_threads_lock);
+ num_threads++;
+ pthread_mutex_unlock(&num_threads_lock);
+
+ // Allocate icmp receive buffer
+ buf = malloc(icmp_receive_buf_len);
+
+ // Start forwarding :)
+ pt_log(kLog_info, "Ping proxy is listening in %s mode.\n", (unprivileged ? "unprivileged" : "privileged"));
+
+ #ifndef WIN32
+ #ifdef HAVE_SELINUX
+ if (uid || gid || selinux_context)
+ #else
+ if (uid || gid)
+ #endif
+ pt_log(kLog_info, "Dropping privileges now.\n");
+ if (gid && -1 == setgid(gid))
+ pt_log(kLog_error, "setgid(%d): %s\n", gid, strerror(errno));
+ if (uid && -1 == setuid(uid))
+ pt_log(kLog_error, "setuid(%d): %s\n", uid, strerror(errno));
+ #ifdef HAVE_SELINUX
+ if (NULL != selinux_context && -1 == setcon(selinux_context))
+ pt_log(kLog_error, "setcon(%s) failed: %s\n", selinux_context, strerror(errno));
+ #endif
+ #endif
+
+ while (1) {
+ FD_ZERO(&set);
+ FD_SET(fwd_sock, &set);
+ max_sock = fwd_sock+1;
+ pthread_mutex_lock(&chain_lock);
+ for (cur=chain;cur;cur=cur->next) {
+ if (cur->sock) {
+ FD_SET(cur->sock, &set);
+ if (cur->sock >= max_sock)
+ max_sock = cur->sock+1;
+ }
+ }
+ pthread_mutex_unlock(&chain_lock);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 10000;
+ select(max_sock, &set, 0, 0, &timeout); // Don't care about return val, since we need to check for new states anyway..
+
+ pthread_mutex_lock(&chain_lock);
+ for (prev=0,cur=chain;cur && cur->sock;cur=tmp) {
+ // Client: If we're starting up, send a message to the remote end saying so,
+ // causing him to connect to our desired endpoint.
+ if (cur->state == kProxy_start) {
+ pt_log(kLog_verbose, "Sending proxy request.\n");
+ cur->last_ack = time_as_double();
+ queue_packet(fwd_sock, cur->pkt_type, 0, 0, cur->id_no, cur->id_no, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, cur->dst_ip, cur->dst_port, cur->state | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ cur->xfer.icmp_out++;
+ cur->state = kProto_data;
+ }
+ if (cur->should_remove) {
+ pt_log(kLog_info, "\nSession statistics:\n");
+ print_statistics(&cur->xfer, 0);
+ pt_log(kLog_info, "\n");
+ tmp = cur->next;
+ remove_proxy_desc(cur, prev);
+ continue;
+ }
+ // Only handle traffic if there is traffic on the socket, we have
+ // room in our send window AND we either don't use a password, or
+ // have been authenticated.
+ if (FD_ISSET(cur->sock, &set) && cur->send_wait_ack < kPing_window_size && (!password || cur->authenticated)) {
+ bytes = recv(cur->sock, cur->buf, tcp_receive_buf_len, 0);
+ if (bytes <= 0) {
+ pt_log(kLog_info, "Connection closed or lost.\n");
+ tmp = cur->next;
+ send_termination_msg(cur, fwd_sock);
+ pt_log(kLog_info, "Session statistics:\n");
+ print_statistics(&cur->xfer, 0);
+ remove_proxy_desc(cur, prev);
+ // No need to update prev
+ continue;
+ }
+ cur->xfer.bytes_out += bytes;
+ cur->xfer.icmp_out++;
+ queue_packet(fwd_sock, cur->pkt_type, cur->buf, bytes, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, cur->state | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ }
+ prev = cur;
+ tmp = cur->next;
+ }
+ pthread_mutex_unlock(&chain_lock);
+
+ if (FD_ISSET(fwd_sock, &set)) {
+ // Handle ping traffic
+ addr_len = sizeof(struct sockaddr);
+ bytes = recvfrom(fwd_sock, buf, icmp_receive_buf_len, 0, (struct sockaddr*)&addr, &addr_len);
+ if (bytes < 0) {
+ pt_log(kLog_error, "Error receiving packet on ICMP socket: %s\n", strerror(errno));
+ break;
+ }
+ handle_packet(buf, bytes, 0, &addr, fwd_sock);
+ }
+
+ // Check for packets needing resend, and figure out if any connections
+ // should be closed down due to inactivity.
+ pthread_mutex_lock(&chain_lock);
+ now = time_as_double();
+ for (cur=chain;cur;cur=cur->next) {
+ if (cur->last_activity + kAutomatic_close_timeout < now) {
+ pt_log(kLog_info, "Dropping tunnel to %s:%d due to inactivity.\n", inet_ntoa(*(struct in_addr*)&cur->dst_ip), cur->dst_port, cur->id_no);
+ cur->should_remove = 1;
+ continue;
+ }
+ if (cur->recv_wait_send && cur->sock)
+ cur->xfer.bytes_in += send_packets(cur->recv_ring, &cur->recv_xfer_idx, &cur->recv_wait_send, &cur->sock);
+
+ // Check for any icmp packets requiring resend, and resend _only_ the first packet.
+ idx = cur->send_first_ack;
+ if (cur->send_ring[idx].pkt && cur->send_ring[idx].last_resend+kResend_interval < now) {
+ pt_log(kLog_debug, "Resending packet with seq-no %d.\n", cur->send_ring[idx].seq_no);
+ cur->send_ring[idx].last_resend = now;
+ cur->send_ring[idx].pkt->seq = htons(cur->ping_seq);
+ cur->ping_seq++;
+ cur->send_ring[idx].pkt->checksum = 0;
+ cur->send_ring[idx].pkt->checksum = htons(calc_icmp_checksum((uint16_t*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len));
+ //printf("ID: %d\n", htons(cur->send_ring[idx].pkt->identifier));
+ sendto(fwd_sock, (const void*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len, 0, (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr));
+ cur->xfer.icmp_resent++;
+ }
+ // Figure out if it's time to send an explicit acknowledgement
+ if (cur->last_ack+1.0 < now && cur->send_wait_ack < kPing_window_size && cur->remote_ack_val+1 != cur->next_remote_seq) {
+ cur->last_ack = now;
+ queue_packet(fwd_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, cur->dst_ip, cur->dst_port, kProto_ack | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ cur->xfer.icmp_ack_out++;
+ }
+ }
+ pthread_mutex_unlock(&chain_lock);
+ if (pcap) {
+ if (pcap_dispatch(pc.pcap_desc, 32, pcap_packet_handler, (u_char*)&pc.pkt_q) > 0) {
+ pqueue_elem_t *cur;
+ //pt_log(kLog_verbose, "pcap captured %d packets - handling them..\n", pc.pkt_q.elems);
+ while (pc.pkt_q.head) {
+ cur = pc.pkt_q.head;
+ memset(&addr, sizeof(struct sockaddr), 0);
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *(in_addr_t*)&(((ip_packet_t*)(cur->data))->src_ip);
+ handle_packet(cur->data, cur->bytes, 1, &addr, fwd_sock);
+ pc.pkt_q.head = cur->next;
+ free(cur);
+ pc.pkt_q.elems--;
+ }
+ pc.pkt_q.tail = 0;
+ pc.pkt_q.head = 0;
+ }
+ }
+ // Update running statistics, if requested (only once every second)
+ if (print_stats && mode == kMode_forward && now > last_status_update+1) {
+ pthread_mutex_lock(&chain_lock);
+ memset(&xfer, 0, sizeof(xfer_stats_t));
+ for (cur=chain;cur;cur=cur->next) {
+ xfer.bytes_in += cur->xfer.bytes_in;
+ xfer.bytes_out += cur->xfer.bytes_out;
+ xfer.icmp_in += cur->xfer.icmp_in;
+ xfer.icmp_out += cur->xfer.icmp_out;
+ xfer.icmp_resent += cur->xfer.icmp_resent;
+ }
+ pthread_mutex_unlock(&chain_lock);
+ print_statistics(&xfer, 1);
+ last_status_update = now;
+ }
+ }
+ pt_log(kLog_debug, "Proxy exiting..\n");
+ if (fwd_sock)
+ close(fwd_sock);
+ // TODO: Clean up the other descs. Not really a priority since there's no
+ // real way to quit ptunnel in the first place..
+ free(buf);
+ pt_log(kLog_debug, "Ping proxy done\n");
+ return 0;
+}
+
+
+/* print_statistics: Prints transfer statistics for the given xfer block. The
+ is_continuous variable controls the output mode, either printing a new line
+ or overwriting the old line.
+*/
+void print_statistics(xfer_stats_t *xfer, int is_continuous) {
+ const double mb = 1024.0*1024.0;
+ double loss = 0.0;
+
+ if (xfer->icmp_out > 0)
+ loss = (double)xfer->icmp_resent/(double)xfer->icmp_out;
+
+ if (is_continuous)
+ printf("\r");
+
+ printf("[inf]: I/O: %6.2f/%6.2f mb ICMP I/O/R: %8d/%8d/%8d Loss: %4.1f%%",
+ xfer->bytes_in/mb, xfer->bytes_out/mb, xfer->icmp_in, xfer->icmp_out, xfer->icmp_resent, loss);
+
+ if (!is_continuous)
+ printf("\n");
+ else
+ fflush(stdout);
+}
+
+
+/* pcap_packet_handler:
+ This is our callback function handling captured packets. We already know that the packets
+ are ICMP echo or echo-reply messages, so all we need to do is strip off the ethernet header
+ and append it to the queue descriptor (the refcon argument).
+
+ Ok, the above isn't entirely correct (we can get other ICMP types as well). This function
+ also has problems when it captures packets on the loopback interface. The moral of the
+ story: Don't do ping forwarding over the loopback interface.
+
+ Also, we currently don't support anything else than ethernet when in pcap mode. The reason
+ is that I haven't read up on yet on how to remove the frame header from the packet..
+*/
+void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt) {
+ pqueue_t *q;
+ pqueue_elem_t *elem;
+ ip_packet_t *ip;
+
+ //pt_log(kLog_verbose, "Packet handler: %d =? %d\n", hdr->caplen, hdr->len);
+ q = (pqueue_t*)refcon;
+ elem = malloc(sizeof(pqueue_elem_t)+hdr->caplen-sizeof(struct ether_header));
+ memcpy(elem->data, pkt+sizeof(struct ether_header), hdr->caplen-sizeof(struct ether_header));
+ ip = (ip_packet_t*)elem->data;
+ // TODO: Add fragment support
+ elem->bytes = ntohs(ip->pkt_len);
+ if (elem->bytes > hdr->caplen-sizeof(struct ether_header)) {
+ pt_log(kLog_error, "Received fragmented packet - unable to reconstruct!\n");
+ pt_log(kLog_error, "This error usually occurs because pcap is used on devices that are not wlan or ethernet.\n");
+ free(elem);
+ return;
+ }
+ //elem->bytes = hdr->caplen-sizeof(struct ether_header);
+ elem->next = 0;
+ if (q->tail) {
+ q->tail->next = elem;
+ q->tail = elem;
+ }
+ else {
+ q->head = elem;
+ q->tail = elem;
+ }
+ q->elems++;
+}
+
+
+
+/* handle_proxy_packet:
+ Processes incoming ICMP packets for the proxy. The packet can come either from the
+ packet capture lib, or from the actual socket or both.
+ Input: A buffer pointing at the start of an IP header, the buffer length and the proxy
+ descriptor chain.
+*/
+void handle_packet(char *buf, int bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock) {
+ ip_packet_t *ip_pkt;
+ icmp_echo_packet_t *pkt;
+ ping_tunnel_pkt_t *pt_pkt;
+ proxy_desc_t *cur;
+ uint32_t type_flag, pkt_flag, init_state;
+ challenge_t *challenge;
+ struct timeval tt;
+
+ if (bytes < sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t))
+ pt_log(kLog_verbose, "Skipping this packet - too short. Expect: %d+%d = %d ; Got: %d\n", sizeof(icmp_echo_packet_t), sizeof(ping_tunnel_pkt_t), sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t), bytes);
+ else {
+ if (use_udp) {
+ ip_pkt = 0;
+ pkt = (icmp_echo_packet_t*)buf;
+ pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ }
+ else {
+ ip_pkt = (ip_packet_t*)buf;
+ pkt = (icmp_echo_packet_t*)ip_pkt->data;
+ pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ }
+ if (ntohl(pt_pkt->magic) == kPing_tunnel_magic) {
+ pt_pkt->state = ntohl(pt_pkt->state);
+ pkt->identifier = ntohs(pkt->identifier);
+ pt_pkt->id_no = ntohs(pt_pkt->id_no);
+ pt_pkt->seq_no = ntohs(pt_pkt->seq_no);
+ // Find the relevant connection, if it exists
+ pthread_mutex_lock(&chain_lock);
+ for (cur=chain;cur;cur=cur->next) {
+ if (cur->id_no == pt_pkt->id_no)
+ break;
+ }
+ pthread_mutex_unlock(&chain_lock);
+
+ /* Handle the packet if it comes from "the other end." This is a bit tricky
+ to get right, since we receive both our own and the other end's packets.
+ Basically, a proxy will accept any packet from a user, regardless if it
+ has a valid connection or not. A user will only accept the packet if there
+ exists a connection to handle it.
+ */
+ if (cur) {
+ type_flag = cur->type_flag;
+ if (type_flag == kProxy_flag)
+ cur->icmp_id = pkt->identifier;
+
+ if (!is_pcap)
+ cur->xfer.icmp_in++;
+ }
+ else
+ type_flag = kProxy_flag;
+
+ pkt_flag = pt_pkt->state & kFlag_mask;
+ pt_pkt->state &= ~kFlag_mask;
+ pt_log(kLog_sendrecv, "Recv: %d [%d] bytes [seq = %d] [type = %s] [ack = %d] [icmp = %d] [user = %s] [pcap = %d]\n",
+ bytes, ntohl(pt_pkt->data_len), pt_pkt->seq_no, state_name[pt_pkt->state & (~kFlag_mask)],
+ ntohl(pt_pkt->ack), pkt->type, (pkt_flag == kUser_flag ? "yes" : "no"), is_pcap);
+
+ // This test essentially verifies that the packet comes from someone who isn't us.
+ if ((pkt_flag == kUser_flag && type_flag == kProxy_flag) || (pkt_flag == kProxy_flag && type_flag == kUser_flag)) {
+ pt_pkt->data_len = ntohl(pt_pkt->data_len);
+ pt_pkt->ack = ntohl(pt_pkt->ack);
+ if (pt_pkt->state == kProxy_start) {
+ if (!cur && type_flag == kProxy_flag) {
+ pt_log(kLog_info, "Incoming tunnel request from %s.\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr));
+ gettimeofday(&tt, 0);
+ if (tt.tv_sec < seq_expiry_tbl[pt_pkt->id_no]) {
+ pt_log(kLog_verbose, "Dropping request: ID was recently in use.\n");
+ return;
+ }
+ pt_log(kLog_info, "Starting new session to %s:%d with ID %d\n", inet_ntoa(*(struct in_addr*)&pt_pkt->dst_ip), ntohl(pt_pkt->dst_port), pt_pkt->id_no);
+ if ((given_dst_ip && given_dst_ip != pt_pkt->dst_ip) || (-1 != tcp_port && tcp_port != ntohl(pt_pkt->dst_port))) {
+ pt_log(kLog_info, "Destination administratively prohibited!\n");
+ return;
+ }
+ if (password)
+ init_state = kProto_authenticate;
+ else
+ init_state = kProto_data;
+ cur = create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0, addr, pt_pkt->dst_ip, ntohl(pt_pkt->dst_port), init_state, kProxy_flag);
+ if (init_state == kProto_authenticate) {
+ pt_log(kLog_debug, "Sending authentication challenge..\n");
+ // Send challenge
+ cur->challenge = generate_challenge();
+ memcpy(cur->buf, cur->challenge, sizeof(challenge_t));
+ queue_packet(icmp_sock, cur->pkt_type, cur->buf, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ }
+ }
+ else if (type_flag == kUser_flag) {
+ pt_log(kLog_error, "Dropping proxy session request - we are not a proxy!\n");
+ return;
+ }
+ else
+ pt_log(kLog_error, "Dropping duplicate proxy session request.\n");
+ }
+ else if (cur && pt_pkt->state == kProto_authenticate) {
+ // Sanity check packet length, and make sure it matches what we expect
+ if (pt_pkt->data_len != sizeof(challenge_t)) {
+ pt_log(kLog_error, "Received challenge packet, but data length is not as expected.\n");
+ pt_log(kLog_debug, "Data length: %d Expected: %d\n", pt_pkt->data_len, sizeof(challenge_t));
+ cur->should_remove = 1;
+ return;
+ }
+ // Prevent packet data from being forwarded over TCP!
+ pt_pkt->data_len = 0;
+ challenge = (challenge_t*)pt_pkt->data;
+ // If client: Compute response to challenge
+ if (type_flag == kUser_flag) {
+ if (!password) {
+ pt_log(kLog_error, "This proxy requires a password! Please supply one using the -x switch.\n");
+ send_termination_msg(cur, icmp_sock);
+ cur->should_remove = 1;
+ return;
+ }
+ pt_log(kLog_debug, "Got authentication challenge - sending response\n");
+ generate_response(challenge);
+ queue_packet(icmp_sock, cur->pkt_type, (char*)challenge, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ // We have authenticated locally. It's up to the proxy now if it accepts our response or not..
+ cur->authenticated = 1;
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
+ return;
+ }
+ // If proxy: Handle client's response to challenge
+ else if (type_flag == kProxy_flag) {
+ pt_log(kLog_debug, "Received remote challenge response.\n");
+ if (validate_challenge(cur->challenge, challenge) || cur->authenticated) {
+ pt_log(kLog_verbose, "Remote end authenticated successfully.\n");
+ // Authentication has succeeded, so now we can proceed to handle incoming TCP data.
+ cur->authenticated = 1;
+ cur->state = kProto_data;
+ // Insert the packet into the receive ring, to avoid confusing the reliability mechanism.
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
+ }
+ else {
+ pt_log(kLog_info, "Remote end failed authentication.\n");
+ send_termination_msg(cur, icmp_sock);
+ cur->should_remove = 1;
+ }
+ return;
+ }
+ }
+ // Handle close-messages for connections we know about
+ if (cur && pt_pkt->state == kProto_close) {
+ pt_log(kLog_info, "Received session close from remote peer.\n");
+ cur->should_remove = 1;
+ return;
+ }
+ // The proxy will ignore any other packets from the client
+ // until it has been authenticated. The packet resend mechanism
+ // insures that this isn't problematic.
+ if (type_flag == kProxy_flag && password && cur && !cur->authenticated) {
+ pt_log(kLog_debug, "Ignoring packet with seq-no %d - not authenticated yet.\n", pt_pkt->seq_no);
+ return;
+ }
+
+ if (cur && cur->sock) {
+ if (pt_pkt->state == kProto_data || pt_pkt->state == kProxy_start || pt_pkt->state == kProto_ack)
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
+ handle_ack((uint16_t)pt_pkt->ack, cur->send_ring, &cur->send_wait_ack, 0, cur->send_idx, &cur->send_first_ack, &cur->remote_ack_val, is_pcap);
+ cur->last_activity = time_as_double();
+ }
+ }
+ }
+ else
+ pt_log(kLog_verbose, "Ignored incoming packet.\n");
+ }
+}
+
+
+
+/* create_and_insert_proxy_desc: Creates a new proxy descriptor, linking it into
+ the descriptor chain. If the sock argument is 0, the function will establish
+ a TCP connection to the ip and port given by dst_ip, dst_port.
+*/
+proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id, int sock, struct sockaddr_in *addr, uint32_t dst_ip, uint32_t dst_port, uint32_t init_state, uint32_t type) {
+ proxy_desc_t *cur;
+
+ pthread_mutex_lock(&chain_lock);
+ if (num_tunnels >= max_tunnels) {
+ pt_log(kLog_info, "Discarding incoming connection - too many tunnels! Maximum count is %d (adjust with the -m switch).\n", max_tunnels);
+ if (sock)
+ close(sock);
+ pthread_mutex_unlock(&chain_lock);
+ return 0;
+ }
+ num_tunnels++;
+ pthread_mutex_unlock(&chain_lock);
+
+ pt_log(kLog_debug, "Adding proxy desc to run loop. Type is %s. Will create socket: %s\n", (type == kUser_flag ? "user" : "proxy"), (sock ? "No" : "Yes"));
+ cur = calloc(1, sizeof(proxy_desc_t));
+ cur->id_no = id_no;
+ cur->dest_addr = *addr;
+ cur->dst_ip = dst_ip;
+ cur->dst_port = dst_port;
+ cur->icmp_id = icmp_id;
+ if (!sock) {
+ cur->sock = socket(AF_INET, SOCK_STREAM, 0);
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_port = htons((uint16_t)dst_port);
+ addr->sin_addr.s_addr = dst_ip;
+ addr->sin_family = AF_INET;
+ // Let's just assume success, shall we?
+ if (connect(cur->sock, (struct sockaddr*)addr, sizeof(struct sockaddr_in)) < 0) {
+ pt_log(kLog_error, "Connect to %s:%d failed: %s\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr.s_addr), ntohs(addr->sin_port), strerror(errno));
+ }
+ }
+ else
+ cur->sock = sock;
+ cur->state = init_state;
+ cur->type_flag = type;
+ if (cur->type_flag == kUser_flag)
+ cur->pkt_type = kICMP_echo_request;
+ else
+ cur->pkt_type = (unprivileged ? kICMP_echo_request : kICMP_echo_reply);
+ cur->buf = malloc(icmp_receive_buf_len);
+ cur->last_activity = time_as_double();
+ cur->authenticated = 0;
+
+ pthread_mutex_lock(&chain_lock);
+ cur->next = chain;
+ chain = cur;
+ pthread_mutex_unlock(&chain_lock);
+ cur->xfer.bytes_in = 0.0;
+ cur->xfer.bytes_out = 0.0;
+ return cur;
+}
+
+
+/* remove_proxy_desc: Removes the given proxy desc, freeing its resources.
+ Assumes that we hold the chain_lock.
+*/
+void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) {
+ int i;
+ struct timeval tt;
+
+ pt_log(kLog_debug, "Removing proxy descriptor.\n");
+ // Get a timestamp, for making an entry in the seq_expiry_tbl
+ gettimeofday(&tt, 0);
+ seq_expiry_tbl[cur->id_no] = tt.tv_sec+(2*kAutomatic_close_timeout);
+
+ // Free resources associated with connection
+ if (cur->buf)
+ free(cur->buf);
+ cur->buf = 0;
+ for (i=0;i<kPing_window_size;i++) {
+ if (cur->send_ring[i].pkt)
+ free(cur->send_ring[i].pkt);
+ cur->send_ring[i].pkt = 0;
+ if (cur->recv_ring[i])
+ free(cur->recv_ring[i]);
+ cur->recv_ring[i] = 0;
+ }
+ close(cur->sock);
+ cur->sock = 0;
+
+ // Keep list up-to-date
+ if (prev)
+ prev->next = cur->next;
+ else
+ chain = cur->next;
+ if (cur->challenge)
+ free(cur->challenge);
+ free(cur);
+ num_tunnels--;
+}
+
+#if kPT_add_iphdr
+static int ip_id_counter = 1;
+#endif
+
+/* queue_packet:
+ Creates an ICMP packet descriptor, and sends it. The packet descriptor is added
+ to the given send ring, for potential resends later on.
+*/
+int queue_packet(int icmp_sock, uint8_t type, char *buf, int num_bytes, uint16_t id_no, uint16_t icmp_id, uint16_t *seq, icmp_desc_t ring[], int *insert_idx, int *await_send, uint32_t ip, uint32_t port, uint32_t state, struct sockaddr_in *dest_addr, uint16_t next_expected_seq, int *first_ack, uint16_t *ping_seq) {
+ #if kPT_add_iphdr
+ ip_packet_t *ip_pkt = 0;
+ int pkt_len = sizeof(ip_packet_t)+sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t)+num_bytes,
+ #else
+ int pkt_len = sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t)+num_bytes,
+ #endif
+ err = 0;
+ icmp_echo_packet_t *pkt = 0;
+ ping_tunnel_pkt_t *pt_pkt = 0;
+ uint16_t ack_val = next_expected_seq-1;
+
+
+ if (pkt_len % 2)
+ pkt_len++;
+
+ #if kPT_add_iphdr
+ printf("add header\n");
+ ip_pkt = malloc(pkt_len);
+ pkt = (icmp_echo_packet_t*)ip_pkt->data;
+ memset(ip_pkt, 0, sizeof(ip_packet_t));
+ ip_pkt->vers_ihl = 0x45;//|(pkt_len>>2);//5;//(IPVERSION << 4) | (sizeof(ip_packet_t) >> 2);
+ ip_pkt->tos = IPTOS_LOWDELAY;
+ ip_pkt->pkt_len = pkt_len;
+ ip_pkt->id = 0; //kernel sets proper value htons(ip_id_counter);
+ ip_pkt->flags_frag_offset = 0;
+ ip_pkt->ttl = IPDEFTTL; // default time to live (64)
+ ip_pkt->proto = 1; // ICMP
+ ip_pkt->checksum = 0; // maybe the kernel helps us out..?
+ ip_pkt->src_ip = htonl(0x0); // insert source IP address here
+ ip_pkt->dst_ip = dest_addr->sin_addr.s_addr;//htonl(0x7f000001); // localhost..
+ #else
+ pkt = malloc(pkt_len);
+ #endif
+
+ pkt->type = type; // ICMP Echo request or reply
+ pkt->code = 0; // Must be zero (non-zero requires root)
+ pkt->identifier = htons(icmp_id);
+ pkt->seq = htons(*ping_seq);
+ pkt->checksum = 0;
+ (*ping_seq)++;
+ // Add our information
+ pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ pt_pkt->magic = htonl(kPing_tunnel_magic);
+ pt_pkt->dst_ip = ip;
+ pt_pkt->dst_port = htonl(port);
+ pt_pkt->ack = htonl(ack_val);
+ pt_pkt->data_len = htonl(num_bytes);
+ pt_pkt->state = htonl(state);
+ pt_pkt->seq_no = htons(*seq);
+ pt_pkt->id_no = htons(id_no);
+ // Copy user data
+ if (buf && num_bytes > 0)
+ memcpy(pt_pkt->data, buf, num_bytes);
+ #if kPT_add_iphdr
+ pkt->checksum = htons(calc_icmp_checksum((uint16_t*)pkt, pkt_len-sizeof(ip_packet_t)));
+ ip_pkt->checksum = htons(calc_icmp_checksum((uint16_t*)ip_pkt, sizeof(ip_packet_t)));
+ #else
+ pkt->checksum = htons(calc_icmp_checksum((uint16_t*)pkt, pkt_len));
+ #endif
+
+ // Send it!
+ pt_log(kLog_sendrecv, "Send: %d [%d] bytes [seq = %d] [type = %s] [ack = %d] [icmp = %d] [user = %s]\n",
+ pkt_len, num_bytes, *seq, state_name[state & (~kFlag_mask)], ack_val, type, ((state & kUser_flag) == kUser_flag ? "yes" : "no"));
+ #if kPT_add_iphdr
+ err = sendto(icmp_sock, (const void*)ip_pkt, pkt_len, 0, (struct sockaddr*)dest_addr, sizeof(struct sockaddr));
+ #else
+ err = sendto(icmp_sock, (const void*)pkt, pkt_len, 0, (struct sockaddr*)dest_addr, sizeof(struct sockaddr));
+ #endif
+ if (err < 0) {
+ pt_log(kLog_error, "Failed to send ICMP packet: %s\n", strerror(errno));
+ return -1;
+ }
+ else if (err != pkt_len)
+ pt_log(kLog_error, "WARNING WARNING, didn't send entire packet\n");
+
+ // Update sequence no's and so on
+ #if kPT_add_iphdr
+ // NOTE: Retry mechanism needs update for PT_add_ip_hdr
+ ring[*insert_idx].pkt = ip_pkt;
+ #else
+ ring[*insert_idx].pkt = pkt;
+ #endif
+ ring[*insert_idx].pkt_len = pkt_len;
+ ring[*insert_idx].last_resend = time_as_double();
+ ring[*insert_idx].seq_no = *seq;
+ ring[*insert_idx].icmp_id = icmp_id;
+ (*seq)++;
+ if (!ring[*first_ack].pkt)
+ *first_ack = *insert_idx;
+ (*await_send)++;
+ (*insert_idx)++;
+ if (*insert_idx >= kPing_window_size)
+ *insert_idx = 0;
+ return 0;
+}
+
+
+/* send_packets:
+ Examines the passed-in ring, and forwards data in it over TCP.
+*/
+uint32_t send_packets(forward_desc_t *ring[], int *xfer_idx, int *await_send, int *sock) {
+ forward_desc_t *fwd_desc;
+ int bytes, total = 0;
+
+ while (*await_send > 0) {
+ fwd_desc = ring[*xfer_idx];
+ if (!fwd_desc) // We haven't got this packet yet..
+ break;
+ if (fwd_desc->length > 0) {
+ bytes = send(*sock, &fwd_desc->data[fwd_desc->length - fwd_desc->remaining], fwd_desc->remaining, 0);
+ if (bytes < 0) {
+ printf("Weirdness.\n");
+ // TODO: send close stuff
+ close(*sock);
+ *sock = 0;
+ break;
+ }
+ fwd_desc->remaining -= bytes;
+ total += bytes;
+ }
+ if (!fwd_desc->remaining) {
+ ring[*xfer_idx] = 0;
+ free(fwd_desc);
+ (*xfer_idx)++;
+ (*await_send)--;
+ if (*xfer_idx >= kPing_window_size)
+ *xfer_idx = 0;
+ }
+ else
+ break;
+ }
+ return total;
+}
+
+
+/* handle_data:
+ Utility function for handling kProto_data packets, and place the data it contains
+ onto the passed-in receive ring.
+*/
+void handle_data(icmp_echo_packet_t *pkt, int total_len, forward_desc_t *ring[], int *await_send, int *insert_idx, uint16_t *next_expected_seq) {
+ ping_tunnel_pkt_t *pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ int expected_len = sizeof(ip_packet_t) + sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t); // 20+8+28
+
+ /* Place packet in the receive ring, in its proper place.
+ This works as follows:
+ -1. Packet == ack packet? Perform ack, and continue.
+ 0. seq_no < next_remote_seq, and absolute difference is bigger than w size => discard
+ 1. If seq_no == next_remote_seq, we have no problems; just put it in the ring.
+ 2. If seq_no > next_remote_seq + remaining window size, discard packet. Send resend request for missing packets.
+ 3. Else, put packet in the proper place in the ring (don't overwrite if one is already there), but don't increment next_remote_seq_no
+ 4. If packed was not discarded, process ack info in packet.
+ */
+ expected_len += pt_pkt->data_len;
+ expected_len += expected_len % 2;
+ if (use_udp)
+ expected_len -= sizeof(ip_packet_t);
+ if (total_len < expected_len) {
+ pt_log(kLog_error, "Packet not completely received: %d Should be: %d. For some reason, this error is fatal.\n", total_len, expected_len);
+ pt_log(kLog_debug, "Data length: %d Total length: %d\n", pt_pkt->data_len, total_len);
+ // TODO: This error isn't fatal, so it should definitely be handled in some way. We could simply discard it.
+ exit(0);
+ }
+ if (pt_pkt->seq_no == *next_expected_seq) {
+ // hmm, what happens if this test is true?
+ if (!ring[*insert_idx]) { // && pt_pkt->state == kProto_data
+ // pt_log(kLog_debug, "Queing data packet: %d\n", pt_pkt->seq_no);
+ ring[*insert_idx] = create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data);
+ (*await_send)++;
+ (*insert_idx)++;
+ }
+ else if (ring[*insert_idx])
+ pt_log(kLog_debug, "Dup packet?\n");
+
+ (*next_expected_seq)++;
+ if (*insert_idx >= kPing_window_size)
+ *insert_idx = 0;
+ // Check if we have already received some of the next packets
+ while (ring[*insert_idx]) {
+ if (ring[*insert_idx]->seq_no == *next_expected_seq) {
+ (*next_expected_seq)++;
+ (*insert_idx)++;
+ if (*insert_idx >= kPing_window_size)
+ *insert_idx = 0;
+ }
+ else
+ break;
+ }
+ }
+ else {
+ int r, s, d, pos;
+ pos = -1; // If pos ends up staying -1, packet is discarded.
+ r = *next_expected_seq;
+ s = pt_pkt->seq_no;
+ d = s - r;
+ if (d < 0) { // This packet _may_ be old, or seq_no may have wrapped around
+ d = (s+0xFFFF) - r;
+ if (d < kPing_window_size) {
+ // Counter has wrapped, so we should add this packet to the recv ring
+ pos = ((*insert_idx)+d) % kPing_window_size;
+ }
+ }
+ else if (d < kPing_window_size)
+ pos = ((*insert_idx)+d) % kPing_window_size;
+
+ if (pos != -1) {
+ if (!ring[pos]) {
+ pt_log(kLog_verbose, "Out of order. Expected: %d Got: %d Inserted: %d (cur = %d)\n", *next_expected_seq, pt_pkt->seq_no, pos, (*insert_idx));
+ ring[pos] = create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data);
+ (*await_send)++;
+ }
+ }
+ //else
+ // pt_log(kLog_debug, "Packet discarded - outside receive window.\n");
+ }
+}
+
+
+void handle_ack(uint16_t seq_no, icmp_desc_t ring[], int *packets_awaiting_ack, int one_ack_only, int insert_idx, int *first_ack, uint16_t *remote_ack, int is_pcap) {
+ int i, j, k;
+ ping_tunnel_pkt_t *pt_pkt;
+
+ if (*packets_awaiting_ack > 0) {
+ if (one_ack_only) {
+ for (i=0;i<kPing_window_size;i++) {
+ if (ring[i].pkt && ring[i].seq_no == seq_no && !is_pcap) {
+ pt_log(kLog_debug, "Received ack for only seq %d\n", seq_no);
+ pt_pkt = (ping_tunnel_pkt_t*)ring[i].pkt->data;
+ *remote_ack = (uint16_t)ntohl(pt_pkt->ack); // WARNING: We make the dangerous assumption here that packets arrive in order!
+ free(ring[i].pkt);
+ ring[i].pkt = 0;
+ (*packets_awaiting_ack)--;
+ if (i == *first_ack) {
+ for (j=1;j<kPing_window_size;j++) {
+ k = (i+j)%kPing_window_size;
+ if (ring[k].pkt) {
+ *first_ack = k;
+ break;
+ }
+ if (k == i) // we have looped through everything
+ *first_ack = insert_idx;
+ j++;
+ }
+ }
+ return;
+ }
+ }
+ }
+ else {
+ int i, can_ack = 0, count = 0;
+ i = insert_idx-1;
+ if (i < 0)
+ i = kPing_window_size - 1;
+
+ pt_log(kLog_debug, "Received ack-series starting at seq %d\n", seq_no);
+ while (count < kPing_window_size) {
+ if (!ring[i].pkt)
+ break;
+
+ if (ring[i].seq_no == seq_no)
+ can_ack = 1;
+ else if (!can_ack)
+ *first_ack = i;
+
+ if (can_ack) {
+ free(ring[i].pkt);
+ ring[i].pkt = 0;
+ (*packets_awaiting_ack)--;
+ }
+ i--;
+ if (i < 0)
+ i = kPing_window_size - 1;
+ count++;
+ }
+ }
+ }
+// else
+// pt_log(kLog_verbose, "Dropping superfluous acknowledgement (no outstanding packets needing ack.)\n");
+}
+
+
+
+forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) {
+ forward_desc_t *fwd_desc;
+ fwd_desc = malloc(sizeof(forward_desc_t)+data_len);
+ fwd_desc->seq_no = seq_no;
+ fwd_desc->length = data_len;
+ fwd_desc->remaining = data_len;
+ if (data_len > 0)
+ memcpy(fwd_desc->data, data, data_len);
+ return fwd_desc;
+}
+
+
+uint16_t calc_icmp_checksum(uint16_t *data, int bytes) {
+ uint32_t sum;
+ int i;
+
+ sum = 0;
+ for (i=0;i<bytes/2;i++) {
+ // WARNING; this might be a bug, but might explain why I occasionally
+ // see buggy checksums.. (added htons, that might be the correct behaviour)
+ sum += data[i];
+ }
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ sum = htons(0xFFFF - sum);
+ return sum;
+}
+
+
+/* generate_challenge: Generates a random challenge, incorporating the current
+ local timestamp to avoid replay attacks.
+*/
+challenge_t* generate_challenge(void) {
+ struct timeval tt;
+ challenge_t *c;
+ int i;
+
+ c = calloc(1, sizeof(challenge_t));
+ gettimeofday(&tt, 0);
+ c->sec = tt.tv_sec;
+ c->usec_rnd = tt.tv_usec + rand();
+ for (i=0;i<6;i++)
+ c->random[i] = rand();
+
+ return c;
+}
+
+
+/* generate_response: Generates a response to the given challenge. The response
+ is generated by combining the concatenating the challenge data with the
+ md5 digest of the password, and then calculating the MD5 digest of the
+ entire buffer. The result is stored in the passed-in challenge, overwriting
+ the challenge data.
+*/
+void generate_response(challenge_t *challenge) {
+ md5_byte_t *buf;
+ md5_state_t state;
+
+ buf = malloc(sizeof(challenge_t)+kMD5_digest_size);
+ memcpy(buf, challenge, sizeof(challenge_t));
+ memcpy(&buf[sizeof(challenge_t)], password_digest, kMD5_digest_size);
+ memset(challenge, 0, sizeof(challenge_t));
+ md5_init(&state);
+ md5_append(&state, buf, sizeof(challenge_t)+kMD5_digest_size);
+ md5_finish(&state, (md5_byte_t*)challenge);
+}
+
+
+/* validate_challenge: Checks whether a given response matches the expected
+ response, returning 1 if validation succeeded, and 0 otherwise. Note that
+ overwriting the local challenge with the challenge result is not a problem,
+ as the data will not be used again anyway (authentication either succeeds,
+ or the connection is closed down).
+*/
+int validate_challenge(challenge_t *local, challenge_t *remote) {
+ generate_response(local);
+ if (memcmp(local, remote, sizeof(challenge_t)) == 0)
+ return 1;
+ return 0;
+}
+
+
+/* send_termination_msg: Sends two packets to the remote end, informing it that
+ the tunnel is being closed down.
+*/
+void send_termination_msg(proxy_desc_t *cur, int icmp_sock) {
+ // Send packet twice, hoping at least one of them makes it through..
+ queue_packet(icmp_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_close | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ queue_packet(icmp_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_close | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
+ cur->xfer.icmp_out += 2;
+}
+
+
+void pt_log(int level, char *fmt, ...) {
+ va_list args;
+ const char *header[] = { "[err]: ",
+ "[inf]: ",
+ "[evt]: ",
+ "[vbs]: ",
+ "[dbg]: ",
+ "[xfr]: " };
+#ifndef WIN32
+ int syslog_levels[] = {LOG_ERR, LOG_NOTICE, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG};
+#endif /* !WIN32 */
+
+ if (level <= log_level) {
+ va_start(args, fmt);
+#ifndef WIN32
+ if (use_syslog) {
+ char log[255];
+ int header_len;
+ header_len = snprintf(log,sizeof(log),"%s",header[level]);
+ vsnprintf(log+header_len,sizeof(log)-header_len,fmt,args);
+ syslog(syslog_levels[level], "%s", log);
+ }
+ else
+#endif /* !WIN32 */
+ fprintf(log_file, "%s", header[level]), vfprintf(log_file, fmt, args);
+ va_end(args);
+#ifndef WIN32
+ if (log_file != stdout && !use_syslog)
+#else
+ if (log_file != stdout)
+#endif
+ fflush(log_file);
+ }
+}
+
+
+double time_as_double(void) {
+ double result;
+ struct timeval tt;
+
+ gettimeofday(&tt, 0);
+ result = (double)tt.tv_sec + ((double)tt.tv_usec / (double)10e5);
+ return result;
+}
diff --git a/ptunnel.h b/ptunnel.h
new file mode 100755
index 0000000..70b673b
--- /dev/null
+++ b/ptunnel.h
@@ -0,0 +1,419 @@
+/* ptunnel.h
+ ptunnel is licensed under the BSD license:
+
+ Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
+ Yellow Lemon Software. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of the Yellow Lemon Software nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Contacting the author:
+ You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe,
+ in case your text editor didn't realize), here: <daniels@cs.uit.no>
+
+ The official ptunnel website is here:
+ <http://www.cs.uit.no/~daniels/PingTunnel/>
+
+ Note that the source code is best viewed with tabs set to 4 spaces.
+*/
+
+#ifndef PING_TUNNEL_H
+ #define PING_TUNNEL_H
+
+// Includes
+#ifndef WIN32
+ #include <sys/unistd.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <pthread.h>
+ #include <errno.h>
+ #include <net/ethernet.h>
+ #include <syslog.h>
+ #include <pwd.h>
+ #include <grp.h>
+#endif /* !WIN32 */
+ #include <stdarg.h>
+ #include <unistd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+ #include <sys/time.h>
+ #include <signal.h>
+ #include <stdint.h>
+ #include <pcap.h>
+
+#ifdef WIN32
+ #include <winsock2.h>
+ typedef int socklen_t;
+ typedef uint32_t in_addr_t;
+ #define ETH_ALEN 6 /* Octets in one ethernet addr */
+ struct ether_header
+ {
+ u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
+ u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
+ u_int16_t ether_type; /* packet type ID field */
+ };
+#endif /* WIN32 */
+
+// Constants
+#define false 0
+#define true 1
+#define bool char
+
+enum {
+ kOpt_undefined = 0, // Constants for parsing options
+ kOpt_set_proxy_addr,
+ kOpt_set_mode,
+ kOpt_set_password,
+ kOpt_set_tcp_port,
+ kOpt_set_tcp_dest_addr,
+ kOpt_set_tcp_dest_port,
+ kOpt_set_verbosity,
+ kOpt_set_max_tunnels,
+ kOpt_set_non_privileged,
+ kOpt_set_pcap_device,
+ kOpt_set_log_file,
+ kOpt_set_unpriv_user,
+ kOpt_set_unpriv_group,
+ kOpt_set_root_dir,
+ kOpt_set_selinux_context,
+ kOpt_daemonize,
+
+ kMode_forward = 0, // Ping tunnel's operating mode (client or
+ kMode_proxy, // proxy)
+
+ kMax_tunnels = 10,/* Set this constant to the number of concurrent
+ connections you wish to handle by default. */
+
+ kNo_log = -1, // Different verbosity levels.
+ kLog_error = 0,
+ kLog_info,
+ kLog_event,
+ kLog_verbose,
+ kLog_debug,
+ kLog_sendrecv,
+
+ kMajor_version = 0, // Major (0.xx) and minor (x.70) version
+ kMinor_version = 72, // numbers.
+
+ kIP_packet_max_size = 576,
+ kIP_header_size = 20, // In bytes, mind you
+ kIP_actual_size = (kIP_packet_max_size - kIP_header_size) - ((kIP_packet_max_size - kIP_header_size) % 8),
+ kICMP_header_size = 8, // Also in bytes
+
+ kDefault_buf_size = 1024, /* This constant control the maximum size of
+ the payload-portion of the ICMP packets
+ we send. Note that this does not include
+ the IP or ICMP headers! */
+
+ kICMP_echo_request = 8, // Type code for echo request and replies
+ kICMP_echo_reply = 0,
+
+ kPing_window_size = 64, // number of packets we can have in our send/receive ring
+
+ /* Tunnels are automatically closed after one minute of inactivity. Since
+ we continously send acknowledgements between the two peers, this mechanism
+ won't disconnect "valid" connections.
+ */
+ kAutomatic_close_timeout = 60, // Seconds!
+
+ kMD5_digest_size = 16, // size of md5 digest in bytes
+
+ /* These constants are used to indicate the protocol state. The protocol
+ works as follows:
+ - The identifier is used by both the proxy and the forwarder
+ to identify the session (and thus the relevant sockets).
+ - The seq-no of the ping packet is used in a sliding-window-esque
+ way, and to identify the order of data.
+
+ The protocol can be in any of the following states:
+ kProxy_start Causes the proxy to open a connection to the given
+ host and port, associating the ID with the socket,
+ before the data on the socket are transmitted.
+ kProxy_data Indicates that the packet contains data from the proxy.
+ Data ordering is indicated by the seq-no, which will start
+ at 0. (The proxy and forwarder maintain different seq-nos.)
+ kUser_data This packet contains user data.
+ kConnection_close Indicates that the connection is being closed.
+ kProxy_ack and Acknowledges the packet (and all packets before it) with seq_no = ack.
+ kUser_ack This is used if there are no implicit acknowledgements due to data
+ being sent.
+
+ Acknowledgements work by the remote peer acknowledging the last
+ continuous seq no it has received.
+
+ Note: A proxy receiving a kProxy_data packet, or a user receiving a
+ kUser_data packet, should ignore it, as it is the host operating system
+ actually returning the ping. This is mostly relevant for users, and for
+ proxies running in unprivileged mode.
+ */
+ kProxy_start = 0,
+ kProto_ack,
+ kProto_data,
+ kProto_close,
+ kProto_authenticate,
+ kNum_proto_types,
+
+ kUser_flag = 1 << 30, // set when packet comes from a user
+ kProxy_flag = 1 << 31, // set when packet comes from the proxy
+ kFlag_mask = kUser_flag | kProxy_flag,
+
+ kDNS_port = 53,
+};
+
+#define kPing_tunnel_magic 0xD5200880
+// Resend packets after this interval (in seconds)
+#define kResend_interval 1.5
+
+/* ping_tunnel_pkt_t: This data structure represents the header of a ptunnel
+ packet, consisting of a magic number, the tunnel's destination IP and port,
+ as well as some other fields. Note that the dest IP and port is only valid
+ in packets from the client to the proxy.
+*/
+typedef struct {
+ uint32_t magic, // magic number, used to identify ptunnel packets.
+ dst_ip, // destination IP and port (used by proxy to figure
+ dst_port, // out where to tunnel to)
+ state, // current connection state; see constants above.
+ ack, // sequence number of last packet received from other end
+ data_len; // length of data buffer
+ uint16_t seq_no, // sequence number of this packet
+ id_no; // id number, used to separate different tunnels from each other
+ char data[0]; // optional data buffer
+} __attribute__ ((packed)) ping_tunnel_pkt_t;
+
+
+/* ip_packet_t: This is basically my own definition of the IP packet, which
+ of course complies with the official definition ;) See any good book on IP
+ (or even the RFC) for info on the contents of this packet.
+*/
+typedef struct {
+ uint8_t vers_ihl,
+ tos;
+ uint16_t pkt_len,
+ id,
+ flags_frag_offset;
+ uint8_t ttl,
+ proto; // 1 for ICMP
+ uint16_t checksum;
+ uint32_t src_ip,
+ dst_ip;
+ char data[0];
+} __attribute__ ((packed)) ip_packet_t;
+
+
+/* icmp_echo_packet_t: This is the definition of a standard ICMP header. The
+ ptunnel packets are constructed as follows:
+ [ ip header (20 bytes) ]
+ [ icmp header (8 bytes) ]
+ [ ptunnel header (28 bytes) ]
+
+ We actually only create the ICMP and ptunnel headers, the IP header is
+ taken care of by the OS.
+*/
+typedef struct {
+ uint8_t type,
+ code;
+ uint16_t checksum,
+ identifier,
+ seq;
+ char data[0];
+} __attribute__ ((packed)) icmp_echo_packet_t;
+
+
+/* pt_thread_info_t: A simple (very simple, in fact) structure that allows us
+ to pass an arbitrary number of params to the threads we create. Currently,
+ that's just one single parameter: The socket which the thread should listen
+ to.
+*/
+typedef struct {
+ int sock;
+} pt_thread_info_t;
+
+
+/* forward_desc_t: Describes a piece of that needs to be forwarded. This
+ structure is used for receiving data from the network, and for subsequent
+ forwarding over TCP:
+
+ 1. Client sends data to proxy over ICMP
+ 2. Proxy receives the data, and puts it into a forward_desc_t
+ 3. The proxy starts send()-ing the data over the TCP socket to the destination,
+ decreasing forward_desc_t->remaining with the number of bytes transferred.
+ 4. Once remaining reaches 0, the forward_desc_t is removed from the receive
+ ring.
+
+ The same procedure is followed in proxy-to-client communication. Just replace
+ proxy with client and vice versa in the list above.
+*/
+typedef struct {
+ int seq_no, // ping_tunnel_pkt_t seq_no
+ length, // length of data
+ remaining; // amount of data not yet transferred
+ char data[0];
+} forward_desc_t;
+
+
+/* icmp_desc_t: This structure is used to track the ICMP packets sent by either
+ the client or proxy. The last_resend variable is used to prevent resending
+ the packet too often. Once the packet is acknowledged by the remote end,
+ it will be removed from the send-ring, freeing up space for more outgoing
+ ICMP packets.
+*/
+typedef struct {
+ int pkt_len; // total length of ICMP packet, including ICMP header and ptunnel data.
+ double last_resend;
+ int resend_count;
+ uint16_t seq_no,
+ icmp_id;
+ icmp_echo_packet_t *pkt;
+} icmp_desc_t;
+
+
+/* challenge_t: This structure contains the pseudo-random challenge used for
+ authentication.
+*/
+typedef struct challenge_t {
+ uint32_t sec, // tv_sec as returned by gettimeofday
+ usec_rnd, // tv_usec as returned by gettimeofday + random value
+ random[6]; // random values
+} __attribute__ ((packed)) challenge_t;
+
+
+/* xfer_stats_t: Various transfer statistics, such as bytes sent and received,
+ number of ping packets sent/received, etc.
+*/
+typedef struct xfer_stats_t {
+ double bytes_in,
+ bytes_out;
+ uint32_t icmp_in,
+ icmp_out,
+ icmp_resent,
+ icmp_ack_out;
+} xfer_stats_t;
+
+
+/* proxy_desc_t: This massive structure describes a tunnel instance.
+*/
+typedef struct proxy_desc_t {
+ int sock, // ICMP or UDP socket
+ bytes, // number of bytes in receive buffer
+ should_remove; // set to true once this instance should be removed
+ char *buf; // data buffer, used to receive ping and pong packets
+ uint16_t id_no,
+ my_seq,
+ ping_seq,
+ next_remote_seq,
+ pkt_type,
+ remote_ack_val,
+ icmp_id;
+ int recv_idx, // first available slot in recv ring
+ recv_xfer_idx, // current slot in recv ring being transferred
+ send_idx, // first available slot in send ring
+ send_first_ack, // first packet in send ring not yet acked
+ recv_wait_send, // number of items in recv ring awaiting send
+ send_wait_ack, // number of items in send ring awaiting ack
+ next_resend_start,
+ authenticated;
+ challenge_t *challenge; // Contains the challenge, if used.
+ uint32_t state, // Protocol state
+ type_flag, // Either kProxy_flag or kUser_flag
+ dst_ip, // IP and port to which data should be forwarded.
+ dst_port;
+ struct sockaddr_in dest_addr; // Same as above
+ double last_ack, // Time when last ack packet was sent.
+ last_activity; // Time when a packet was last received.
+ icmp_desc_t send_ring[kPing_window_size];
+ forward_desc_t *recv_ring[kPing_window_size];
+ xfer_stats_t xfer;
+ struct proxy_desc_t *next;
+} proxy_desc_t;
+
+
+/* pqueue_elem_t: An queue element in the pqueue structure (below).
+*/
+typedef struct pqueue_elem_t {
+ int bytes; // size of data buffer
+ struct pqueue_elem_t *next; // next queue element (if any)
+ char data[0]; // data (duh!)
+} pqueue_elem_t;
+
+
+/* pqueue_t: A simple queue strucutre.
+*/
+typedef struct {
+ pqueue_elem_t *head,
+ *tail;
+ int elems;
+} pqueue_t;
+
+/* pcap_info_t: Structure to hold information related to packet capturing.
+*/
+typedef struct {
+ pcap_t *pcap_desc;
+ struct bpf_program fp; // Compiled filter program
+ uint32_t netp,
+ netmask;
+ char *pcap_err_buf, // Buffers for error and packet info
+ *pcap_data_buf;
+ pqueue_t pkt_q; // Queue of packets to process
+} pcap_info_t;
+
+
+// Prototypes (sorry about the long lines..)
+ void usage(char *exec_name);
+ void* pt_proxy(void *args);
+ void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt);
+ void handle_packet(char *buf, int bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock);
+
+ proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id, int sock, struct sockaddr_in *addr, uint32_t dst_ip, uint32_t dst_port, uint32_t init_state, uint32_t type);
+ void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev);
+
+ void pt_forwarder(void);
+
+ void print_statistics(xfer_stats_t *xfer, int is_continuous);
+ int queue_packet(int icmp_sock, uint8_t type, char *buf, int num_bytes, uint16_t id_no, uint16_t icmp_id, uint16_t *seq, icmp_desc_t ring[], int *insert_idx, int *await_send, uint32_t ip, uint32_t port, uint32_t state, struct sockaddr_in *dest_addr, uint16_t next_expected_seq, int *first_ack, uint16_t *ping_seq);
+ uint32_t send_packets(forward_desc_t *ring[], int *xfer_idx, int *await_send, int *sock);
+ void handle_data(icmp_echo_packet_t *pkt, int total_len, forward_desc_t *ring[], int *await_send, int *insert_idx, uint16_t *next_expected_seq);
+ void handle_ack(uint16_t seq_no, icmp_desc_t ring[], int *packets_awaiting_ack, int one_ack_only, int insert_idx, int *first_ack, uint16_t *remote_ack, int is_pcap);
+ forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data);
+ void init_ip_packet(ip_packet_t *packet, uint16_t id, uint16_t frag_offset, uint16_t pkt_len, uint8_t ttl, uint32_t src_ip, uint32_t dst_ip, bool is_last_frag, bool dont_frag);
+ uint16_t calc_ip_checksum(ip_packet_t *pkt);
+ uint16_t calc_icmp_checksum(uint16_t *data, int bytes);
+
+ challenge_t* generate_challenge(void);
+ void generate_response(challenge_t *challenge);
+ int validate_challenge(challenge_t *local, challenge_t *remote);
+
+ void send_termination_msg(proxy_desc_t *cur, int icmp_sock);
+
+ char* f_inet_ntoa(uint32_t ip);
+ void pt_log(int level, char *fmt, ...);
+ double time_as_double(void);
+#endif
diff --git a/redhat/._ptunnel.spec b/redhat/._ptunnel.spec
new file mode 100644
index 0000000..48fe56d
--- /dev/null
+++ b/redhat/._ptunnel.spec
Binary files differ
diff --git a/redhat/ptunnel.spec b/redhat/ptunnel.spec
new file mode 100644
index 0000000..590280e
--- /dev/null
+++ b/redhat/ptunnel.spec
@@ -0,0 +1,71 @@
+# $Id: $
+# Authority: dries
+# Upstream: Daniel Stodle <daniels$stud,cs,uit,no>
+
+%define real_name PingTunnel
+
+Summary: Reliably tunnel TCP connections over ICMP packets
+Name: ptunnel
+Version: 0.70
+Release: 1.rf
+License: BSD
+Group: Applications/Internet
+URL: http://www.cs.uit.no/~daniels/PingTunnel/index.html
+
+Packager: Dries Verachtert <dries@ulyssis.org>
+Vendor: Dag Apt Repository, http://dag.wieers.com/apt/
+
+Source: http://www.cs.uit.no/~daniels/PingTunnel/PingTunnel-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
+
+BuildRequires: libpcap
+
+%description
+Ping Tunnel is a tool for reliably tunneling TCP connections over ICMP echo
+request and reply packets (commonly known as ping requests and replies). It
+is useful for evading firewalls that, for whatever reason, prevent outgoing
+TCP connections, but allow in- and outgoing ICMP packets. The tunnel works
+by having a proxy run on a machine ping-able from the inside of the
+firewall, with the client running on the local machine from which TCP access
+is required.
+
+%prep
+%setup -n %{real_name}
+
+%build
+%{__make} %{?_smp_mflags}
+
+%install
+%{__rm} -rf %{buildroot}
+%makeinstall mandir="%{buildroot}%{_mandir}/man8"
+
+%clean
+%{__rm} -rf %{buildroot}
+
+%files
+%defattr(-, root, root, 0755)
+%doc CHANGELOG LICENSE README web/
+%doc %{_mandir}/man8/ptunnel.8*
+%{_bindir}/ptunnel
+
+%changelog
+* Wed Jan 12 2009 Michael Grigorev <sleuthhound@gmail.com> - 0.70
+- Updated to release 0.70.
+
+* Fri May 27 2005 Dag Wieers <dag@wieers.com> - 0.61-1 - 3200+/dag
+- Updated to release 0.61.
+
+* Sat Apr 30 2005 Dag Wieers <dag@wieers.com> - 0.60-1
+- Updated to release 0.60.
+
+* Mon Feb 21 2005 Dag Wieers <dag@wieers.com> - 0.55-1
+- Updated to release 0.55.
+
+* Sun Feb 06 2005 Dag Wieers <dag@wieers.com> - 0.54-1
+- Updated to release 0.54.
+
+* Mon Jan 03 2005 Dries Verachtert <dries@ulyssis.org> - 0.52-1
+- Updated to release 0.52 (Makefile patch applied by author).
+
+* Sun Jan 02 2005 Dries Verachtert <dries@ulyssis.org> - 0.51-1
+- Initial package.
diff --git a/selinux/CVS/Entries b/selinux/CVS/Entries
new file mode 100644
index 0000000..32b83d2
--- /dev/null
+++ b/selinux/CVS/Entries
@@ -0,0 +1,2 @@
+/ptunnel.te/1.1/Mon Jun 22 08:09:46 2009//
+D
diff --git a/selinux/CVS/Repository b/selinux/CVS/Repository
new file mode 100644
index 0000000..f41a656
--- /dev/null
+++ b/selinux/CVS/Repository
@@ -0,0 +1 @@
+pingtunnel/selinux
diff --git a/selinux/CVS/Root b/selinux/CVS/Root
new file mode 100644
index 0000000..d2a18e8
--- /dev/null
+++ b/selinux/CVS/Root
@@ -0,0 +1 @@
+:ext:daniels@lgserv3.stud.cs.uit.no:/users/daniels/cvsroot
diff --git a/selinux/ptunnel.te b/selinux/ptunnel.te
new file mode 100644
index 0000000..995c765
--- /dev/null
+++ b/selinux/ptunnel.te
@@ -0,0 +1,22 @@
+policy_module(ptunnel, 1.7)
+
+require {
+ type initrc_t;
+ type unconfined_t;
+ type unlabeled_t;
+ class tcp_socket { read write create connect };
+ class association recvfrom;
+ class rawip_socket { write read };
+}
+
+type ptunnel_t;
+domain_dyntrans_type(initrc_t)
+
+allow ptunnel_t self:tcp_socket { read write create connect };
+allow ptunnel_t unconfined_t:rawip_socket { write read };
+allow ptunnel_t unlabeled_t:association recvfrom;
+corenet_tcp_sendrecv_generic_if(ptunnel_t)
+corenet_tcp_sendrecv_ssh_port(ptunnel_t)
+corenet_raw_receive_generic_node(ptunnel_t)
+corenet_tcp_connect_ssh_port(ptunnel_t)
+corenet_tcp_sendrecv_lo_node(ptunnel_t)
diff --git a/web/._index.html b/web/._index.html
new file mode 100755
index 0000000..79a7755
--- /dev/null
+++ b/web/._index.html
Binary files differ
diff --git a/web/._setup.png b/web/._setup.png
new file mode 100755
index 0000000..0ddac7c
--- /dev/null
+++ b/web/._setup.png
Binary files differ
diff --git a/web/index.html b/web/index.html
new file mode 100755
index 0000000..1df601a
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,266 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+<title>Ping Tunnel - Send TCP traffic over ICMP</title>
+</head>
+<body>
+<TABLE BORDER=0 BGCOLOR="#999999" CELLSPACING=0 CELLPADDING=5 WIDTH="100%">
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="100%" COLSPAN=2>
+<h1>Ping Tunnel</h1>
+<h4>For those times when everything else is blocked.</h4>
+<h5>By Daniel St&oslash;dle, daniels@cs.uit.no</h5>
+<h5><i>Last updated: 5. September 2011</i></h5>
+<hr>
+<h3>Contents</h3>
+<ul>
+<li><a href="#what">What is it?</a></li>
+<li><a href="#features">Features and requirements</a></li>
+<li><a href="#features">How it works</a></li>
+<li><a href="#download">Download</a></li>
+<li><a href="#using">Using ptunnel</a></li>
+<li><a href="#changes">Changes</a></li>
+<li><a href="#license">License</a></li>
+</ul>
+<hr>
+
+<a name="what"><h3>What is it?</h3></a>
+Ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. At first glance, this might seem like a rather useless thing to do, but it can actually come in handy in some cases. The following example illustrates the main motivation in creating ptunnel:<p>
+
+Setting: You're on the go, and stumble across an open wireless network. The network gives you an IP address, but won't let you send TCP or UDP packets out to the rest of the internet, for instance to check your mail. What to do? By chance, you discover that the network will allow you to ping any computer on the rest of the internet. With ptunnel, you can utilize this feature to check your mail, or do other things that require TCP.<p>
+
+<a name="features"><h3>Features and requirements</h3></a>
+Ptunnel is not a feature-rich tool by any means, but it does what it advertises. So here is what it can do:<p>
+<ul><li>Tunnel TCP using ICMP echo request and reply packets</li>
+<li>Connections are reliable (lost packets are resent as necessary)</li>
+<li>Handles multiple connections</li>
+<li>Acceptable bandwidth (150 kb/s downstream and about 50 kb/s upstream are the currently measured maximas for one tunnel, but with tweaking this can be improved further)</li>
+<li>Authentication, to prevent just anyone from using your proxy</li>
+</ul>
+
+So what do you need for all this to work?<p>
+
+<ul><li>One computer accessible on the internet that is <i>not</i> firewalled (or at least allows incoming ICMP packets)</li>
+<li>A computer to act as the client (this will usually be your laptop, on the go..)</li>
+<li>Root access, preferably on both computers</li>
+<li>A posix-compliant OS, with libpcap (for packet capturing) and its associated headers installed (typically available in a dev-package on Ubuntu)</li>
+<li>Or: Windows with mingw and WinPcap installed</li>
+</ul>
+
+Compiling the sources simply consists of running make. No ./configure, make, make install, just make. On Windows, you'll need to run make ptunnel.exe, but that's it. The resulting binary is called <b>ptunnel</b>. See the usage section below for info on running it.
+
+</TD></TR>
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="*">
+<a name="how"><h3>How it works</h3></a>
+
+This is a technical description of how ptunnel works. If you're not interested in low-level networking details, you can skip this section. It might help to read it either way, as it provides some insights into the situations where ptunnel <i>doesn't</i> work.
+
+Ptunnel works by tunneling TCP connections over ICMP packets. In the following, we will talk about the <b>proxy,</b> the <b>client</b> and the <b>destination</b>. The proxy is the &quot;endpoint&quot; for our ping packets, i.e. the computer that we send the ping packets to. The client is the computer we're trying to surf the net from, and the destination is the computer we would normally be trying to access over TCP (such as a web site or an ssh server somewhere).<p>
+
+So, in order to accomplish this, we need the ability to send and receive ping packets. Many operating systems enable us to do this using so-called raw sockets. Raw sockets is the preferred mechanism for sending ICMP packets, and is used by both the proxy and the client. Unfortunately, raw sockets require root, so there is a provision for using standard datagram sockets if they are supported by the operating system (Mac OS X 10.2 or later supports this, but Linux systems will require root either way). Ptunnel supports this, however it is not recommended for actual use. We'll get back to the reason later.<p>
+
+The client will perform all its communications using ICMP echo request (ping) packets (type 8), whereas the proxy will use echo reply packets (type 0). In theory, it is possible to have the proxy also use echo request packets (and thus make it operate without root), but these packets are not necessarily forwarded to the client beyond the host network, so they are not used.
+</TD>
+<TD BGCOLOR="#EEEEEE" VALIGN=CENTER WIDTH="*">
+<IMG SRC="setup.png" ALT="Machine setup"><br>
+<center>Figure 1. Networking setup.</center>
+</TD></TR>
+
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="100%" COLSPAN=1>
+<h4>The protocol</h4>
+The proxy protocol uses four different message types combined with sequence numbers and an acknowledgement field. A magic number is used to differentiate our ping requests and replies from &quot;usual&quot; pings. The general packet format (not including the IP or ICMP headers) can be seen in the figure below.<p>
+
+<center><IMG SRC="packet-format.png" ALT="Packet format"><br>
+Figure 2. The packet format used to exchange messages between client and proxy.</center><p>
+
+The IP and port fields are only used in packets from the client to the proxy. They indicate where the client wants the received packets to be forwarded (they are really only used once - when the proxy receives the first message with state code <tt>kProxy_start</tt>).<p>
+</TD>
+<TD BGCOLOR="#EEEEEE" ALIGN=RIGHT VALIGN=CENTER WIDTH="100%" COLSPAN=1>
+State codes:<br>
+<tt>kProxy_start = 0;<br>
+kProto_data = 1;<br>
+kProto_ack = 2;<br>
+kProto_close = 3;<br>
+kProto_authenticate = 4;<br>
+</tt><p>
+
+Identifier flags:<br>
+<tt>kUser_flag = 1 &lt;&lt; 30;<br>
+kProxy_flag = 1 &lt;&lt; 31;<br>
+</tt>
+</TD></TR>
+
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="100%" COLSPAN=2>
+The state code serves a dual purpose. First, it indicates what kind of message is being received - either a message starting a new proxy session (<tt>kProxy_start</tt>), a message containing data to be forwarded (<tt>kProto_data</tt>), an explicit acknowledgement of received packets (<tt>kProto_ack</tt>, a close message (<tt>kProto_close</tt>) or an authentication challenge/response (<tt>kProto_authenticate</tt>). Second, it indicates who sent the message: A message sent by the client will have the <tt>kUser_flag</tt> bit set, whereas a message sent by the proxy has the <tt>kProxy_flag</tt> bit set. This is necessary since a ping request will cause the operating system on the proxy computer to return its own echo reply, which is identical to the packet we just sent to the proxy.
+
+The ack and seq fields are tightly related. Modelled after the use of acknowledgements in TCP, the ptunnel protocol places the sequence number of the last packet received into the ack field of any outgoing message. The seq field is a monotonically increasing 16-bit counter, that is allowed to wrap around (ok, so I guess it's monotonic <i>until</i> it wraps around). Whenever an outgoing packet has been waiting for an acknowledgement too long, the peer will attempt to resend the first packet not yet acknowledged.<p>
+
+The length field simply indicates the length of the data portion of the packet, and is 0 for all other state values than <tt>kProto_data</tt>. Finally the rsv field contains two bytes that are reserved (for now they serve as padding).<p>
+
+On receiving a <tt>kProxy_start</tt> request, a proxy will open a TCP connection to the server given by the ip and port fields. As data comes in over the TCP connection, the proxy will convert the data to ICMP echo reply packets, and send them to the remote peer. The client will do the same, except its packets will always be echo request packets.<p>
+
+<h4>Authentication</h4>
+As of version 0.60, Ping Tunnel supports authentication. The authentication used is very simple, and works as follows. The user first specifies a password or passphrase, which is then hashed using the MD5 algorithm (Ping Tunnel uses the implementation by L. Peter Deutsch, available <a href="http://sourceforge.net/projects/libmd5-rfc/">here</a>. Note that the implementation is included with Ping Tunnel, so there is no need to download it separately).<p>
+
+Whenever a proxy receives a request for a new tunnel, it will respond with an authentication challenge. The challenge consists of a timestamp augmented with random data, totalling 32 bytes. The response is calculated as follows (the + denotes string concatenation):<p>
+
+<tt>md5(challenge + md5(password))</tt><p>
+
+The proxy verifies the result by computing the same md5 sums, and then comparing the two. If authentication succeeds, the proxy allows TCP traffic to start flowing in either direction; if not, the connection is torn down.<p>
+
+<h4>Handling multiple connections</h4>
+The proxy handles multiple different connections by using the ICMP identifier field. A client will randomly generate an identifier when it starts a session, and the remote peer will use this identifier to associate the packets with a connection. The mechanism is not foolproof, but works acceptably as long as no two instances attempt to use the same identifier (there is currently no mechanism for reporting such errors).<p>
+
+The ICMP sequence number field is not used by ptunnel, mostly due to fears that some routers might drop packets whose sequence number repeats. Instead, a separate sequence number is used as part of the ptunnel packet format (see above).<p>
+
+<h4>Send and receive windows</h4>
+Ptunnel uses the simple concept of send and receive windows for controlling the number of packets that can be in-flight at the same time. The window is currently statically allocated at 64 packets, but the number can be tweaked by modifying the ptunnel header file (yes, a recompile is required). Increasing the window size will improve the maximum potential bandwidth.
+
+The send and receive windows are simply implemented as a set of circular arrays, with pointers indicating the next available send/receive slot, and the first non-acked packet.
+
+<h4>Handling packet loss</h4>
+Ptunnel handles packet loss by resending (presumably) lost packets. As it sends packets, it will increment a sequence number. Both the client and proxy maintain their own sequence number, and also a number indicating the last sequence number acknowledged by the remote peer. Whenever too much time (1.5 seconds) passes without a packet being acknowledged, the peer will resend that packet.<p>
+
+Note that the peer will <i>only</i> resend the first missing packet. Once that packet has been acknowledged, it <i>may</i> resend the next packet(s), depending on how many packets were acknowledged. If the next few packets are acknowlegded as well, they are removed from the send queue. It is not uncommon for one packet to get lost, with most of the others making it through. This mechanism avoids unecessary resends as much as possible.<p>
+
+<h4>Congestion control</h4>
+Ptunnel currently does no explicit congestion control. It will send as many ping packets as the window size allows, as slowly or as quickly as it sees fit. This might be improved in the future, if it turns out to be a problem (which is not at all unlikely..).
+
+<h4>When things don't work</h4>
+There are a number of situations where ptunnel will fail. They can briefly be put into the following categories:<br>
+<ol><li>Outgoing/incoming ping not allowed, or filtered by a gateway somewhere along the way
+<li>Operating system causing trouble
+<lI>Probably some other failures as well ;)
+</ol><p>
+
+We can't handle the first failure - if our packets are filtered before we can get at them, there's little we can do. It is possible to deal with the second scenario by using the packet capturing library to get the packets before the OS sees them. This is necessary on Mac OS X, and may be necessary on other platforms as well. The problem lies in that the OS may occasionally not deliver ICMP packets to the raw socket we have opened for sending and receiving. This happens when the ICMP packet is an echo request (which the OS handles by itself) or when the ICMP packet is a resend (for some weird reason). The workaround is to use packet capture, however this tends to diminish bandwidth by quite a bit. For this reason, you should always try to run the proxy without packet capturing, and see if that works first. (This is the default mode.)
+</TD></TR>
+
+
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="100%" COLSPAN=2>
+<a name="download"><h3>Download</h3></a>
+<p>The current version of ptunnel is 0.71, and the source code is available for download <a href="PingTunnel-0.71.tar.gz"><u>here</u></a>. Some other links:</p>
+
+<ul>
+<li><u><a href="http://freshmeat.net/projects/ptunnel/">Freshmeat project page</a></u></li>
+<li>RPMs for different platforms: <a href="http://dries.studentenweb.org/apt/packages/ptunnel/info.html"><u>http://dries.studentenweb.org/apt/packages/ptunnel/info.html</u></a> and
+<a href="http://dag.wieers.com/packages/ptunnel/"><u>http://dag.wieers.com/packages/ptunnel/</u></a></li>
+<li>SPARC/x86 Solaris 2.5-10 packages: <a href="http://sunfreeware.com">http://sunfreeware.com</a></li>
+<li><a href="ptunnel-0.71-iphone.tar.gz">iPhone version</a> (requires a jailbroken iPhone/iPod touch running iPhone OS 3.0 or later with libpcap installed through Cydia), by Rudolf Spring. (Added 29. January 2010)</li></ul>
+
+<p>Ptunnel has so far been tested on a variety of configurations, including Linux Fedora Core 2 and Mac OS X 10.3.6 and above.</p>
+
+Debian users can install Ping Tunnel by adding the following to <tt>/etc/apt/sources.list</tt><p>
+
+<tt>deb http://www.cti.ecp.fr/~beauxir5/debian binary/<br>
+deb-src http://www.cti.ecp.fr/~beauxir5/debian source/</tt><p>
+
+And then run <tt>apt-get update</tt> followed by <tt>apt-get install ptunnel</tt>. A big thanks to Romain Beauxis for taking the time to create a Debian package for ptunnel!<p>
+
+As of version 0.70, ptunnel has support for Windows built-in, thanks to Mike Miller. You will need <a href="http://www.mingw.org/">mingw</a> and <a href="http://www.winpcap.org/">WinPcap</a> <a href="http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip">(download here)</a> installed to compile on Windows. Please note that I don't use Windows, so I can not provide support for compilation-specific issues regarding the Windows port. Wouter van der Veer has been kind enough to provide a compiled Windows binary on his website, which you can <a href="http://vps.galway.nl/ptunnel/ptunnel.exe">download here</a>.<p>
+</TD></TR>
+
+<TR><TD BGCOLOR="#EEEEEE" VALIGN=TOP WIDTH="100%" COLSPAN=2>
+<a name="using"><h3>Using ptunnel</h3></a>
+<tt><b>Client:</b> ./ptunnel -p &lt;proxy address&gt; -lp &lt;listen port&gt; -da &lt;destination address&gt; -dp &lt;destination port&gt; [-c &lt;network device&gt;] [-v &lt;verbosity&gt;] [-f &lt;logfile&gt;] [-u] [-x password]<br>
+<b>Proxy:</b> ./ptunnel [-c &lt;network device&gt;] [-v &lt;verbosity&gt;] [-f &lt;logfile&gt;] [-u] [-x password]</tt><p>
+
+The <tt>-p</tt> switch sets the address of the host on which the proxy is running. A quick test to see if the proxy will work is simply to try pinging this host - if you get replies, you should be able to make the tunnel work.<p>
+
+The <tt>-lp</tt>, <tt>-da</tt> and <tt>-dp</tt> switches set the local listening port, destination address and destination port. For instance, to tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used:<p>
+
+<tt>sudo ./ptunnel -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22</tt><p>
+
+An ssh connection to login.domain.com can now be established as follows:<p>
+
+<tt>ssh -p 8000 localhost</tt><p>
+
+If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the <tt>known_hosts</tt> file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., <tt>ssh localhost</tt>), or you have used ptunnel to forward ssh connections to different hosts.<p>
+
+Of course, for all of this to work, you need to start the proxy on your proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is <i>very</i> simple:<p>
+
+<tt>sudo ./ptunnel</tt><p>
+
+If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the <tt>-c</tt> switch, and supplying the device name to capture packets on (for instance <tt>eth0</tt> or <tt>en1</tt>). The same goes for the client. On versions of Mac OS X prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise.<p>
+
+To protect yourself from others using your proxy, you can protect access to it with a password using the <tt>-x</tt> switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.<p>
+
+Finally, the <tt>-u</tt> switch will attempt to run the proxy in unprivileged mode (i.e., no need for root access), and the <tt>-v</tt> switch controls the amount of output from ptunnel. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides <i>even more</i> output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and
+receives. The <tt>-f</tt> switch allows output to be saved to a logfile.<p>
+
+<a name="changes"><h3>Changes</h3></a>
+0.72 - 5. September 2011<br>
+<ul><li>Fixes an authentication bug that would manifest as hung connections with protocols that send data from the client-side before receiving data from the server-side. Thanks to StalkR for locating the bug and fixing it.</li>
+<li>Fixes a crash when attempting to enable packet-capture for non-existing network devices. Thanks to Steffen Wendzel for the patch.</li></ul><p>
+
+0.71 - 22. June 2009<br>
+<ul><li>Added security features and SELinux support, courtesy of Sebastien Raveau.</li></ul><p>
+
+
+0.70 - 12. January 2009<br>
+<ul><li>Added rudimentary support for tunneling over UDP port 53. This may or may not be useful.</li>
+<li>Added built-in support for compiling on Windows, thanks to Mike Miller.</li>
+<li>Added syslog support, also courtesy of Mike Miller.</li>
+<li>Experimental support for spoofing the source IP address. The source address must be explicitly configured in the source code, and it might not work (which is why it's experimental). To enable, define kPT_add_iphdr to 1.</li></ul><p>
+
+0.62 - <i>Never released</i><br>
+<ul><li>Added many comments to the ptunnel header file.</li>
+<li>Moved most include directives to the header file.</li>
+<li>Fixed crash if proxy or destination hostnames could not be looked up.</li></ul><p>
+
+0.61 - 26. May 2005<br>
+<ul><li>Noted that ptunnel now works without packet capturing on Mac OS X 10.4 Tiger.</li>
+<li>Log files are now opened in append-mode (i.e., not truncated).</li>
+<li>Fixed a bug that could cause ptunnel to crash if passwords shorter than 16 characters were used (the overwhelming majority of passwords, most likely!).</li></ul><p>
+
+0.60 - 15. Apr 2005<br>
+<ul><li>Added authentication support, changing parts of the ptunnel protocol.</li>
+<li>Added a manpage.</li>
+<li>Added MD5 implementation by L. Peter Deutsch for authentication.</li>
+<li>Moved declaration of a variable to allow ptunnel to compile cleanly on gcc 2.95 - thanks Choong!</li>
+<li>Added error handling for proxy connections.</li>
+<li>Fixed a problem with printing send/recv info. All verbosity levels should work now.</li>
+<li>Updated contact info.</li></ul><p>
+
+0.55 - 18. Feb 2005<br>
+<ul><li>Fixed a locking bug that would manifest itself when the maximum connection count on the proxy was reached.</li>
+<li>Fixed ptunnel to compile correctly on 64-bit architectures (thanks to &Aring;smund Grammeltvedt for pointing out the necessary changes!)</li>
+<li>Added a new logging level (level 5). Level 4 no longer outputs send and receive info; for this info level 5 is necessary.</li>
+<li>When libpcap is in use, the interface is no longer put in promiscous mode. This has never been necessary, and also makes it impossible to use ptunnel with more than one client on the same network.</li>
+<li>Discovered a problem with pcap that would cause ptunnel to hang when pcap was in use. This problem has not been resolved; the workaround is to simply re-execute the client, or disable pcap if possible.</li>
+<li>Added support for specifying a log file on the command line, using the -f switch.</li></ul><p>
+
+0.54 - 1. Feb 2005<br>
+<ul><li>Fixed a byte-order bug (thanks Alfred!)</li></ul><p>
+
+0.53 - 31. Jan 2005<br>
+<ul><li>Fixed a threading bug, and implemented support for limiting the maximum number of tunnels.</li></ul><p>
+
+Thanks to Alfred Young for reporting and fixing the following bugs:<br>
+<ul><li>Fixed a bug with packets captured via libpcap, where the struct sockaddr wasn't properly zeroed.</li>
+<li>Fixed a byte order bug in create_and_insert_proxy_desc.</li>
+<li>Fixed a memory leak in remove_proxy_desc.</li></ul><p>
+
+0.52 - 3. Jan 2005<br>
+<ul><li>Fixed a problem introduced by the ICMP ID field changes. The proxy didn't retain the ID of the packets received from clients, resulting in dropped ICMP packets at the router. This in turn lead to the tunnel no longer working, depending on the strictness of the router. This version fixes that problem.
+<li>Makefile is better now, thanks to Dries Verachtert.
+</ul><p>
+
+0.51 - 2. Jan 2005<br>
+<ul><li>Fixed incorrect checksum calculation for resent packets.
+<li>Stopped relying on the ICMP packet's "built-in" ID field, and moved the information to the data portion of the packet.
+<li>Changed default verbosity level from debug to verbose.
+</ul><p>
+
+0.50 - 7. Dec 2004<br>
+Initial public release.
+
+
+<a name="license"><h3>License</h3></a>
+Ptunnel is licensed under the BSD license.<p>
+
+<h3>Feedback</h3>
+I'd be grateful for any feedback you may have - send it to me here: daniels@cs.uit.no. I'm interested in hearing about bugs, suggestions and naturally general criticism. If you find it useful, I'd love to know about that too :)<p>
+</TD></TR>
+</TABLE>
+</body>
+</html>
diff --git a/web/packet-format.png b/web/packet-format.png
new file mode 100755
index 0000000..8184e77
--- /dev/null
+++ b/web/packet-format.png
Binary files differ
diff --git a/web/setup.png b/web/setup.png
new file mode 100755
index 0000000..57f8afd
--- /dev/null
+++ b/web/setup.png
Binary files differ