├── .gitignore ├── CHANGES ├── LICENSE ├── Makefile ├── README.md ├── man └── .keep └── src ├── checksum.c ├── checksum.h ├── client-handlers.c ├── client-handlers.h ├── client.c ├── client.h ├── config.h ├── daemon.c ├── daemon.h ├── echo-skt.c ├── echo-skt.h ├── forwarder.c ├── forwarder.h ├── handlers.h ├── icmptunnel.c ├── options.h ├── peer.h ├── protocol.h ├── resolve.c ├── resolve.h ├── server-handlers.c ├── server-handlers.h ├── server.c ├── server.h ├── tun-device.c └── tun-device.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim swap files 2 | src/*.swp 3 | 4 | # Object files 5 | src/*.o 6 | 7 | # Gzipped man pages 8 | man/*.gz 9 | 10 | # Executables 11 | icmptunnel 12 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 11/07/2016: 0.1-beta 2 | - Initial release. 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 James Barlow-Bignell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # for portability. 2 | SHELL = /bin/sh 3 | CC = gcc 4 | 5 | # compile flags. 6 | CFLAGS = -g -std=c99 -pedantic -Wall -Wextra -Werror -march=native -O2 -fwhole-program -flto 7 | 8 | TARGET = icmptunnel 9 | MANPAGE = icmptunnel.8 10 | SOURCES = $(shell echo src/*.c) 11 | HEADERS = $(shell echo src/*.h) 12 | OBJECTS = $(SOURCES:.c=.o) 13 | VERSION = 0.1-beta 14 | 15 | # installation paths. 16 | PREFIX = $(DESTDIR)/usr/local 17 | BINDIR = $(PREFIX)/sbin 18 | MANDIR = $(PREFIX)/share/man/man8 19 | 20 | # standard targets. 21 | all: $(TARGET) 22 | 23 | $(TARGET): $(OBJECTS) 24 | @echo "[LD] $@" 25 | @$(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) 26 | 27 | man: 28 | @(cd man; gzip < $(MANPAGE) > $(MANPAGE).gz) 29 | 30 | install: $(TARGET) man 31 | @install -D -m 755 $(TARGET) $(BINDIR)/$(TARGET) 32 | @install -D -m 744 man/$(MANPAGE).gz $(MANDIR)/$(MANPAGE).gz 33 | 34 | install-strip: $(TARGET) man 35 | @install -D -m 755 -s $(TARGET) $(BINDIR)/$(TARGET) 36 | @install -D -m 744 man/$(MANPAGE).gz $(MANDIR)/$(MANPAGE).gz 37 | 38 | uninstall: 39 | @$(RM) $(BINDIR)/$(TARGET) 40 | @$(RM) $(MANDIR)/$(MANPAGE).gz 41 | 42 | clean: 43 | @$(RM) $(OBJECTS) 44 | 45 | distclean: clean 46 | @$(RM) $(TARGET) 47 | @(cd man; $(RM) $(MANPAGE).gz) 48 | 49 | %.o: %.c $(HEADERS) 50 | @echo "[CC] $<" 51 | @$(CC) $(CFLAGS) -c -o $@ $< 52 | 53 | .PHONY: all man install install-strip uninstall clean distclean 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | **icmptunnel** is a tool to tunnel IP traffic within ICMP echo request and response (ping) packets. It’s intended for bypassing firewalls in a semi-covert way, for example when pivoting inside a network where ping is allowed. It might also be useful for egress from a corporate network to the Internet, although it is quite common for ICMP echo traffic to be filtered at the network perimeter. 3 | 4 | While there are a couple of existing tools which implement this technique, icmptunnel provides a more reliable protocol and a mechanism for tunneling through stateful firewalls and NAT. 5 | 6 | ##### Compiling: 7 | 8 | The tool uses a plain Makefile to compile and install. 9 | 10 | Use `make` to compile icmptunnel. 11 | 12 | ##### Quickstart: 13 | 14 | First, disable ICMP echo responses on both the client and server. This prevents the kernel from responding to ping packets itself. 15 | 16 | # echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all 17 | 18 | On the server-side, start icmptunnel in server mode, and assign an IP address to the new tunnel interface. 19 | 20 | # ./icmptunnel –s 21 | opened tunnel device: tun0 22 | (ctrl-z) 23 | # bg 24 | # /sbin/ifconfig tun0 10.0.0.1 netmask 255.255.255.0 25 | 26 | On the client-side, point icmptunnel at the server, and assign an IP address. 27 | 28 | # ./icmptunnel 29 | opened tunnel device: tun0 30 | connection established. 31 | (ctrl-z) 32 | # bg 33 | # /sbin/ifconfig tun0 10.0.0.2 netmask 255.255.255.0 34 | 35 | At this point, you should have a functioning point-to-point tunnel via ICMP packets. The server side is 10.0.0.1, and the client-side is 10.0.0.2. On the client, try connecting to the server via SSH: 36 | 37 | # ssh root@10.0.0.1 38 | Password: 39 | 40 | To use the remote server as an encrypted SOCKS proxy: 41 | 42 | # ssh -D 8080 -N root@10.0.0.1 43 | Password: 44 | 45 | Now point your web browser at the local SOCKS server. 46 | 47 | ##### Further Information 48 | 49 | See `./icmptunnel -h` for a list of options. 50 | 51 | ##### Bugs 52 | 53 | Please report any bugs on the Github project page at: 54 | 55 | https://github.com/jamesbarlow/icmptunnel/issues 56 | -------------------------------------------------------------------------------- /man/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesbarlow/icmptunnel/6ec2a4a68a7fdc4f3dff393a341a3874ea791523/man/.keep -------------------------------------------------------------------------------- /src/checksum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "checksum.h" 28 | 29 | uint16_t checksum(const char *buf, int size) 30 | { 31 | uint16_t *p = (uint16_t*)buf; 32 | uint32_t sum = 0; 33 | 34 | /* calculate the sum over the buffer in 2-byte words. */ 35 | for (sum = 0; size > 1; size -= 2) { 36 | sum += *p++; 37 | } 38 | 39 | /* there may be a final byte to sum. */ 40 | if (size == 1) { 41 | sum += *(unsigned char*)p; 42 | } 43 | 44 | /* sum the high and low 16 bits. */ 45 | sum = (sum >> 16) + (sum & 0xffff); 46 | sum += (sum >> 16); 47 | 48 | return ~sum; 49 | } 50 | -------------------------------------------------------------------------------- /src/checksum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_CHECKSUM_H 28 | #define ICMPTUNNEL_CHECKSUM_H 29 | 30 | #include 31 | 32 | /* calculate an icmp checksum. */ 33 | uint16_t checksum(const char *buf, int size); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/client-handlers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "peer.h" 31 | #include "daemon.h" 32 | #include "options.h" 33 | #include "echo-skt.h" 34 | #include "tun-device.h" 35 | #include "protocol.h" 36 | #include "forwarder.h" 37 | #include "client-handlers.h" 38 | 39 | void send_connection_request(struct echo_skt *skt, struct peer *server, int emulation) 40 | { 41 | /* write a connection request packet. */ 42 | struct packet_header *header = (struct packet_header*)skt->data; 43 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 44 | header->type = PACKET_CONNECTION_REQUEST; 45 | 46 | /* send the request. */ 47 | struct echo request; 48 | request.size = sizeof(struct packet_header); 49 | request.reply = 0; 50 | request.id = server->nextid; 51 | request.seq = emulation ? server->nextseq : server->nextseq++; 52 | 53 | send_echo(skt, server->linkip, &request); 54 | } 55 | 56 | void send_punchthru(struct echo_skt *skt, struct peer *server, int emulation) 57 | { 58 | /* write a punchthru packet. */ 59 | struct packet_header *header = (struct packet_header*)skt->data; 60 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 61 | header->type = PACKET_PUNCHTHRU; 62 | 63 | /* send the packet. */ 64 | struct echo request; 65 | request.size = sizeof(struct packet_header); 66 | request.reply = 0; 67 | request.id = server->nextid; 68 | request.seq = emulation ? server->nextseq : server->nextseq++; 69 | 70 | send_echo(skt, server->linkip, &request); 71 | } 72 | 73 | void send_keep_alive(struct echo_skt *skt, struct peer *server, int emulation) 74 | { 75 | /* write a keep-alive request packet. */ 76 | struct packet_header *header = (struct packet_header*)skt->data; 77 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 78 | header->type = PACKET_KEEP_ALIVE; 79 | 80 | /* send the request. */ 81 | struct echo request; 82 | request.size = sizeof(struct packet_header); 83 | request.reply = 0; 84 | request.id = server->nextid; 85 | request.seq = emulation ? server->nextseq : server->nextseq++; 86 | 87 | send_echo(skt, server->linkip, &request); 88 | } 89 | 90 | void handle_connection_accept(struct echo_skt *skt, struct peer *server, struct options *opts) 91 | { 92 | /* if we're already connected then ignore the packet. */ 93 | if (server->connected) 94 | return; 95 | 96 | fprintf(stderr, "connection established.\n"); 97 | 98 | server->connected = 1; 99 | server->timeouts = 0; 100 | 101 | /* fork and run as a daemon if needed. */ 102 | if (opts->daemon) { 103 | if (daemon() != 0) 104 | return; 105 | } 106 | 107 | /* send the initial punch-thru packets. */ 108 | int i; 109 | for (i = 0; i < 10; ++i) { 110 | send_punchthru(skt, server, opts->emulation); 111 | } 112 | } 113 | 114 | void handle_server_full(struct peer *server) 115 | { 116 | /* if we're already connected then ignore the packet. */ 117 | if (server->connected) 118 | return; 119 | 120 | fprintf(stderr, "unable to connect: server is full.\n"); 121 | 122 | /* stop the packet forwarding loop. */ 123 | stop(); 124 | } 125 | 126 | void handle_client_data(struct echo_skt *skt, struct tun_device *device, 127 | struct peer *server, struct echo *echo) 128 | { 129 | /* if we're not connected then drop the packet. */ 130 | if (!server->connected) 131 | return; 132 | 133 | /* determine the size of the encapsulated frame. */ 134 | int framesize = echo->size - sizeof(struct packet_header); 135 | 136 | if (!framesize) 137 | return; 138 | 139 | /* write the frame to the tunnel interface. */ 140 | write_tun_device(device, skt->data + sizeof(struct packet_header), framesize); 141 | 142 | server->timeouts = 0; 143 | } 144 | 145 | void handle_keep_alive_response(struct peer *server) 146 | { 147 | /* if we're not connected then drop the packet. */ 148 | if (!server->connected) 149 | return; 150 | 151 | server->seconds = 0; 152 | server->timeouts = 0; 153 | } 154 | -------------------------------------------------------------------------------- /src/client-handlers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_CLIENT_HANDLERS_H 28 | #define ICMPTUNNEL_CLIENT_HANDLERS_H 29 | 30 | struct peer; 31 | struct options; 32 | struct echo_skt; 33 | struct tun_device; 34 | 35 | /* send a connection request to the server. */ 36 | void send_connection_request(struct echo_skt *skt, struct peer *server, int emulation); 37 | 38 | /* send a punchthru packet. */ 39 | void send_punchthru(struct echo_skt *skt, struct peer *server, int emulation); 40 | 41 | /* send a keep-alive request to the server. */ 42 | void send_keep_alive(struct echo_skt *skt, struct peer *server, int emulation); 43 | 44 | /* handle a connection accept packet. */ 45 | void handle_connection_accept(struct echo_skt *skt, struct peer *server, struct options *opts); 46 | 47 | /* handle a server full packet. */ 48 | void handle_server_full(struct peer *server); 49 | 50 | /* handle a data packet. */ 51 | void handle_client_data(struct echo_skt *skt, struct tun_device *device, struct peer *server, 52 | struct echo *echo); 53 | 54 | /* handle a keep-alive packet. */ 55 | void handle_keep_alive_response(struct peer *server); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "config.h" 31 | #include "options.h" 32 | #include "client.h" 33 | #include "peer.h" 34 | #include "resolve.h" 35 | #include "protocol.h" 36 | #include "echo-skt.h" 37 | #include "tun-device.h" 38 | #include "handlers.h" 39 | #include "forwarder.h" 40 | #include "client-handlers.h" 41 | 42 | /* the server. */ 43 | static struct peer server; 44 | 45 | /* program options. */ 46 | static struct options *opts; 47 | 48 | /* handle an icmp packet. */ 49 | static void handle_icmp_packet(struct echo_skt *skt, struct tun_device *device); 50 | 51 | /* handle data from the tunnel interface. */ 52 | static void handle_tunnel_data(struct echo_skt *skt, struct tun_device *device); 53 | 54 | /* handle a timeout. */ 55 | static void handle_timeout(struct echo_skt *skt); 56 | 57 | int client(const char *hostname, struct options *options) 58 | { 59 | struct echo_skt skt; 60 | struct tun_device device; 61 | 62 | struct handlers handlers = { 63 | &handle_icmp_packet, 64 | &handle_tunnel_data, 65 | &handle_timeout 66 | }; 67 | opts = options; 68 | 69 | /* calculate the required icmp payload size. */ 70 | int bufsize = options->mtu + sizeof(struct packet_header); 71 | 72 | /* resolve the server hostname. */ 73 | if (resolve(hostname, &server.linkip) != 0) 74 | return 1; 75 | 76 | /* open an echo socket. */ 77 | if (open_echo_skt(&skt, bufsize) != 0) 78 | return 1; 79 | 80 | /* open a tunnel interface. */ 81 | if (open_tun_device(&device, options->mtu) != 0) 82 | return 1; 83 | 84 | /* choose initial icmp id and sequence numbers. */ 85 | server.nextid = rand(); 86 | server.nextseq = rand(); 87 | 88 | /* send the initial connection request. */ 89 | send_connection_request(&skt, &server, opts->emulation); 90 | 91 | /* run the packet forwarding loop. */ 92 | int ret = forward(&skt, &device, &handlers); 93 | 94 | close_tun_device(&device); 95 | close_echo_skt(&skt); 96 | 97 | return ret; 98 | } 99 | 100 | void handle_icmp_packet(struct echo_skt *skt, struct tun_device *device) 101 | { 102 | struct echo echo; 103 | uint32_t sourceip; 104 | 105 | /* receive the packet. */ 106 | if (receive_echo(skt, &sourceip, &echo) != 0) 107 | return; 108 | 109 | /* we're only expecting packets from the server. */ 110 | if (sourceip != server.linkip) 111 | return; 112 | 113 | /* we're only expecting echo replies. */ 114 | if (!echo.reply) 115 | return; 116 | 117 | /* check the packet size. */ 118 | if (echo.size < (int)sizeof(struct packet_header)) 119 | return; 120 | 121 | /* check the header magic. */ 122 | struct packet_header *header = (struct packet_header*)skt->data; 123 | 124 | if (memcmp(header->magic, PACKET_MAGIC, sizeof(header->magic)) != 0) 125 | return; 126 | 127 | switch (header->type) { 128 | case PACKET_CONNECTION_ACCEPT: 129 | /* handle a connection accept packet. */ 130 | handle_connection_accept(skt, &server, opts); 131 | break; 132 | 133 | case PACKET_SERVER_FULL: 134 | /* handle a server full packet. */ 135 | handle_server_full(&server); 136 | break; 137 | 138 | case PACKET_DATA: 139 | /* handle a data packet. */ 140 | handle_client_data(skt, device, &server, &echo); 141 | break; 142 | 143 | case PACKET_KEEP_ALIVE: 144 | /* handle a keep-alive packet. */ 145 | handle_keep_alive_response(&server); 146 | break; 147 | } 148 | } 149 | 150 | void handle_tunnel_data(struct echo_skt *skt, struct tun_device *device) 151 | { 152 | int size; 153 | 154 | /* read the frame. */ 155 | if (read_tun_device(device, skt->data + sizeof(struct packet_header), &size) != 0) 156 | return; 157 | 158 | /* if we're not connected then drop the frame. */ 159 | if (!server.connected) 160 | return; 161 | 162 | /* write a data packet. */ 163 | struct packet_header *header = (struct packet_header*)skt->data; 164 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 165 | header->type = PACKET_DATA; 166 | 167 | /* send the encapsulated frame to the server. */ 168 | struct echo echo; 169 | echo.size = sizeof(struct packet_header) + size; 170 | echo.reply = 0; 171 | echo.id = server.nextid; 172 | echo.seq = opts->emulation ? server.nextseq : server.nextseq++; 173 | 174 | send_echo(skt, server.linkip, &echo); 175 | } 176 | 177 | void handle_timeout(struct echo_skt *skt) 178 | { 179 | /* send a punch-thru packet. */ 180 | send_punchthru(skt, &server, opts->emulation); 181 | 182 | /* has the peer timeout elapsed? */ 183 | if (++server.seconds == opts->keepalive) { 184 | server.seconds = 0; 185 | 186 | /* have we reached the max number of retries? */ 187 | if (opts->retries != -1 && ++server.timeouts == opts->retries) { 188 | fprintf(stderr, "connection timed out.\n"); 189 | 190 | /* stop the packet forwarding loop. */ 191 | stop(); 192 | return; 193 | } 194 | 195 | /* if we're still connecting, resend the connection request. */ 196 | if (!server.connected) { 197 | send_connection_request(skt, &server, opts->emulation); 198 | return; 199 | } 200 | 201 | /* otherwise, send a keep-alive request. */ 202 | send_keep_alive(skt, &server, opts->emulation); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_CLIENT_H 28 | #define ICMPTUNNEL_CLIENT_H 29 | 30 | struct options; 31 | 32 | /* run the client. */ 33 | int client(const char *hostname, struct options *options); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_CONFIG_H 28 | #define ICMPTUNNEL_CONFIG_H 29 | 30 | /* program version. */ 31 | #define ICMPTUNNEL_VERSION "0.1-beta" 32 | 33 | /* default timeout in seconds between keep-alive requests. */ 34 | #define ICMPTUNNEL_TIMEOUT 5 35 | 36 | /* default number of retries before a connection is dropped. */ 37 | #define ICMPTUNNEL_RETRIES 5 38 | 39 | /* default interval between punch-thru packets. */ 40 | #define ICMPTUNNEL_PUNCHTHRU_INTERVAL 1 41 | 42 | /* default window size of punch-thru packets. */ 43 | #define ICMPTUNNEL_PUNCHTHRU_WINDOW 10 44 | 45 | /* default tunnel mtu in bytes; assume the size of an ethernet frame. */ 46 | #define ICMPTUNNEL_MTU 1500 47 | 48 | /* default to standard linux behaviour, do not emulate windows ping. */ 49 | #define ICMPTUNNEL_EMULATION 0 50 | 51 | /* default to running in the foreground. */ 52 | #define ICMPTUNNEL_DAEMON 0 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/daemon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | int daemon() 35 | { 36 | int res; 37 | 38 | if ((res = fork()) < 0) { 39 | fprintf(stderr, "unable to fork: %s\n", strerror(errno)); 40 | return -1; 41 | } 42 | 43 | /* if we're the parent process then exit. */ 44 | if (res > 0) 45 | exit(0); 46 | 47 | /* set a new session id. */ 48 | if (setsid() < 0) { 49 | fprintf(stderr, "unable to set sid: %s\n", strerror(errno)); 50 | return -1; 51 | } 52 | 53 | /* redirect the standard streams to /dev/null. */ 54 | int fd; 55 | 56 | if ((fd = open("/dev/null", O_RDWR)) < 0) { 57 | fprintf(stderr, "unable to open /dev/null: %s\n", strerror(errno)); 58 | return -1; 59 | } 60 | /* 61 | int i; 62 | for (i = 0; i < 3; ++i) { 63 | dup2(fd, i); 64 | } 65 | 66 | if (fd >= 2) { 67 | close(fd); 68 | } 69 | */ 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /src/daemon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_DAEMON_H 28 | #define ICMPTUNNEL_DAEMON_H 29 | 30 | /* detach from the terminal and run in the background. */ 31 | int daemon(); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/echo-skt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "checksum.h" 35 | #include "echo-skt.h" 36 | 37 | int open_echo_skt(struct echo_skt *skt, int mtu) 38 | { 39 | skt->buf = skt->data = NULL; 40 | 41 | /* open the icmp socket. */ 42 | if ((skt->fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { 43 | fprintf(stderr, "unable to open icmp socket: %s\n", strerror(errno)); 44 | return 1; 45 | } 46 | 47 | /* calculate the buffer size required to encapsulate this payload. */ 48 | skt->bufsize = mtu + sizeof(struct iphdr) + sizeof(struct icmphdr); 49 | 50 | /* allocate the buffer. */ 51 | if ((skt->buf = malloc(skt->bufsize)) == NULL) { 52 | fprintf(stderr, "unable to allocate icmp tx/rx buffers: %s\n", strerror(errno)); 53 | return 1; 54 | } 55 | 56 | /* save a pointer to the icmp payload for convenience. */ 57 | skt->data = skt->buf + sizeof(struct iphdr) + sizeof(struct icmphdr); 58 | 59 | return 0; 60 | } 61 | 62 | int send_echo(struct echo_skt *skt, uint32_t destip, struct echo* echo) 63 | { 64 | ssize_t xfer; 65 | 66 | struct sockaddr_in dest; 67 | dest.sin_family = AF_INET; 68 | dest.sin_addr.s_addr = htonl(destip); 69 | dest.sin_port = 0; /* for valgrind. */ 70 | 71 | /* write the icmp header. */ 72 | struct icmphdr *header = (struct icmphdr*)(skt->buf + sizeof(struct iphdr)); 73 | header->type = echo->reply ? 0 : 8; 74 | header->code = 0; 75 | header->un.echo.id = htons(echo->id); 76 | header->un.echo.sequence = htons(echo->seq); 77 | header->checksum = 0; 78 | header->checksum = checksum(skt->buf + sizeof(struct iphdr), sizeof(struct icmphdr) + echo->size); 79 | 80 | /* send the packet. */ 81 | xfer = sendto(skt->fd, skt->buf + sizeof(struct iphdr), sizeof(struct icmphdr) + echo->size, 0, 82 | (struct sockaddr*)&dest, sizeof(struct sockaddr_in)); 83 | 84 | if (xfer < 0) { 85 | fprintf(stderr, "unable to send icmp packet: %s\n", strerror(errno)); 86 | return 1; 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | int receive_echo(struct echo_skt *skt, uint32_t *sourceip, struct echo *echo) 93 | { 94 | ssize_t xfer; 95 | struct sockaddr_in source; 96 | socklen_t source_size = sizeof(struct sockaddr_in); 97 | 98 | /* receive a packet. */ 99 | xfer = recvfrom(skt->fd, skt->buf, skt->bufsize, 0, (struct sockaddr*)&source, &source_size); 100 | 101 | if (xfer < 0) { 102 | fprintf(stderr, "unable to receive icmp packet: %s\n", strerror(errno)); 103 | return 1; 104 | } 105 | 106 | /* parse the icmp header. */ 107 | struct icmphdr *header = (struct icmphdr*)(skt->buf + sizeof(struct iphdr)); 108 | 109 | if (xfer < (int)sizeof(struct iphdr) + (int)sizeof(struct icmphdr)) 110 | return 1; /* bad packet size. */ 111 | 112 | if ((header->type != 0 && header->type != 8) || header->code != 0) 113 | return 1; /* unexpected packet type. */ 114 | 115 | *sourceip = ntohl(source.sin_addr.s_addr); 116 | 117 | echo->size = xfer - sizeof(struct iphdr) - sizeof(struct icmphdr); 118 | echo->reply = header->type == 0; 119 | echo->id = ntohs(header->un.echo.id); 120 | echo->seq = ntohs(header->un.echo.sequence); 121 | 122 | return 0; 123 | } 124 | 125 | void close_echo_skt(struct echo_skt *skt) 126 | { 127 | /* dispose of the buffer. */ 128 | if (skt->buf) 129 | free(skt->buf); 130 | 131 | /* close the icmp socket. */ 132 | if (skt->fd >= 0) 133 | close(skt->fd); 134 | } 135 | -------------------------------------------------------------------------------- /src/echo-skt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_ECHOSKT_H 28 | #define ICMPTUNNEL_ECHOSKT_H 29 | 30 | #include 31 | #include 32 | 33 | struct echo_skt 34 | { 35 | int fd; 36 | int bufsize; 37 | char *buf, *data; 38 | }; 39 | 40 | struct echo 41 | { 42 | int size; 43 | int reply; 44 | uint16_t id; 45 | uint16_t seq; 46 | }; 47 | 48 | /* open an icmp echo socket. */ 49 | int open_echo_skt(struct echo_skt *skt, int mtu); 50 | 51 | /* send an echo packet. */ 52 | int send_echo(struct echo_skt *skt, uint32_t destip, struct echo *echo); 53 | 54 | /* receive an echo packet. */ 55 | int receive_echo(struct echo_skt *skt, uint32_t *sourceip, struct echo *echo); 56 | 57 | /* close the socket. */ 58 | void close_echo_skt(struct echo_skt *skt); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/forwarder.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "options.h" 34 | #include "handlers.h" 35 | #include "echo-skt.h" 36 | #include "tun-device.h" 37 | #include "forwarder.h" 38 | 39 | /* are we still running? */ 40 | static int running = 1; 41 | 42 | int forward(struct echo_skt *skt, struct tun_device *device, struct handlers *handlers) 43 | { 44 | int ret; 45 | int maxfd = skt->fd > device->fd ? skt->fd : device->fd; 46 | 47 | struct timeval timeout; 48 | 49 | /* loop and push packets between the tunnel device and peer. */ 50 | while (running) { 51 | fd_set fs; 52 | 53 | FD_ZERO(&fs); 54 | FD_SET(skt->fd, &fs); 55 | FD_SET(device->fd, &fs); 56 | 57 | /* set the timeout. */ 58 | timeout.tv_sec = 1; 59 | timeout.tv_usec = 0; 60 | 61 | /* wait for some data. */ 62 | ret = select(maxfd + 1, &fs, NULL, NULL, &timeout); 63 | 64 | if (ret < 0) { 65 | if (!running) 66 | break; 67 | fprintf(stderr, "unable to select() on sockets: %s\n", strerror(errno)); 68 | return 1; 69 | } 70 | /* did we time out? */ 71 | else if (ret == 0) { 72 | handlers->timeout(skt); 73 | } 74 | 75 | /* handle a packet from the echo socket. */ 76 | if (FD_ISSET(skt->fd, &fs)) { 77 | handlers->icmp(skt, device); 78 | } 79 | 80 | /* handle data from the tunnel device. */ 81 | if (FD_ISSET(device->fd, &fs)) { 82 | handlers->tunnel(skt, device); 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | void stop() 90 | { 91 | running = 0; 92 | } 93 | -------------------------------------------------------------------------------- /src/forwarder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_FORWARDER_H 28 | #define ICMPTUNNEL_FORWARDER_H 29 | 30 | struct handlers; 31 | struct echo_skt; 32 | struct tun_device; 33 | 34 | /* loop and forward packets between the tunnel interface and peer. */ 35 | int forward(struct echo_skt *skt, struct tun_device *device, struct handlers *handlers); 36 | 37 | /* stop the forwarding loop. */ 38 | void stop(); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/handlers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_HANDLERS_H 28 | #define ICMPTUNNEL_HANDLERS_H 29 | 30 | struct echo_skt; 31 | struct tun_device; 32 | 33 | struct handlers 34 | { 35 | /* handle an icmp packet. */ 36 | void (*icmp)(struct echo_skt *skt, struct tun_device *device); 37 | 38 | /* handle data from the tunnel interface. */ 39 | void (*tunnel)(struct echo_skt *skt, struct tun_device *device); 40 | 41 | /* handle a timeout. */ 42 | void (*timeout)(struct echo_skt *skt); 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/icmptunnel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "config.h" 36 | #include "client.h" 37 | #include "server.h" 38 | #include "options.h" 39 | #include "forwarder.h" 40 | 41 | static void version() 42 | { 43 | fprintf(stderr, "icmptunnel is version %s (built %s).\n", ICMPTUNNEL_VERSION, __DATE__); 44 | exit(0); 45 | } 46 | 47 | static void help(const char *program) 48 | { 49 | fprintf(stderr, "icmptunnel %s.\n", ICMPTUNNEL_VERSION); 50 | fprintf(stderr, "usage: %s [options] -s|server\n\n", program); 51 | fprintf(stderr, " -v print version and exit.\n"); 52 | fprintf(stderr, " -h print help and exit.\n"); 53 | fprintf(stderr, " -k interval between keep-alive packets.\n"); 54 | fprintf(stderr, " the default interval is %i seconds.\n", ICMPTUNNEL_TIMEOUT); 55 | fprintf(stderr, " -r packet retry limit before timing out.\n"); 56 | fprintf(stderr, " the default is %i retries.\n", ICMPTUNNEL_RETRIES); 57 | fprintf(stderr, " -m max frame size of the tunnel interface.\n"); 58 | fprintf(stderr, " the default tunnel mtu is %i bytes.\n", ICMPTUNNEL_MTU); 59 | fprintf(stderr, " -e emulate the microsoft ping utility.\n"); 60 | fprintf(stderr, " -d run in the background as a daemon.\n"); 61 | fprintf(stderr, " -s run in server-mode.\n"); 62 | fprintf(stderr, " server run in client-mode, using the server ip/hostname.\n\n"); 63 | exit(0); 64 | } 65 | 66 | static void usage(const char *program) 67 | { 68 | fprintf(stderr, "unknown or missing option -- '%c'\n", optopt); 69 | fprintf(stderr, "use %s -h for more information.\n", program); 70 | exit(1); 71 | } 72 | 73 | static void signalhandler(int sig) 74 | { 75 | /* unused variable. */ 76 | (void)sig; 77 | 78 | stop(); 79 | } 80 | 81 | int main(int argc, char *argv[]) 82 | { 83 | char *program = argv[0]; 84 | char *hostname = NULL; 85 | int servermode = 0; 86 | 87 | struct options options = { 88 | ICMPTUNNEL_TIMEOUT, 89 | ICMPTUNNEL_RETRIES, 90 | ICMPTUNNEL_MTU, 91 | ICMPTUNNEL_EMULATION, 92 | ICMPTUNNEL_DAEMON 93 | }; 94 | 95 | /* parse the option arguments. */ 96 | opterr = 0; 97 | int opt; 98 | while ((opt = getopt(argc, argv, "vhk:r:m:eds")) != -1) { 99 | switch (opt) { 100 | case 'v': 101 | version(); 102 | break; 103 | case 'h': 104 | help(program); 105 | break; 106 | case 'k': 107 | options.keepalive = atoi(optarg); 108 | if (options.keepalive == 0) { 109 | options.keepalive = 1; 110 | } 111 | break; 112 | case 'r': 113 | if (strcmp(optarg, "infinite") == 0) { 114 | options.retries = -1; 115 | } 116 | else { 117 | options.retries = atoi(optarg); 118 | } 119 | break; 120 | case 'm': 121 | options.mtu = atoi(optarg); 122 | break; 123 | case 'e': 124 | options.emulation = 1; 125 | break; 126 | case 'd': 127 | options.daemon = 1; 128 | break; 129 | case 's': 130 | servermode = 1; 131 | break; 132 | case '?': 133 | /* fall-through. */ 134 | default: 135 | usage(program); 136 | break; 137 | } 138 | } 139 | 140 | argc -= optind; 141 | argv += optind; 142 | 143 | /* if we're running in client mode, parse the server hostname. */ 144 | if (!servermode) { 145 | if (argc < 1) { 146 | fprintf(stderr, "missing server ip/hostname.\n"); 147 | fprintf(stderr, "use %s -h for more information.\n", program); 148 | return 1; 149 | } 150 | hostname = argv[0]; 151 | 152 | argc--; 153 | argv++; 154 | } 155 | 156 | /* check for extraneous options. */ 157 | if (argc > 0) { 158 | fprintf(stderr, "unknown option -- '%s'\n", argv[0]); 159 | fprintf(stderr, "use %s -h for more information.\n", program); 160 | return 1; 161 | } 162 | 163 | /* check for root privileges. */ 164 | if (geteuid() != 0) { 165 | fprintf(stderr, "opening raw icmp sockets requires root privileges.\n"); 166 | fprintf(stderr, "are you running as root?\n"); 167 | exit(1); 168 | } 169 | 170 | /* register the signal handlers. */ 171 | signal(SIGINT, signalhandler); 172 | signal(SIGTERM, signalhandler); 173 | 174 | srand(time(NULL)); 175 | 176 | if (servermode) { 177 | /* run the server. */ 178 | return server(&options); 179 | } 180 | 181 | /* run the client. */ 182 | return client(hostname, &options); 183 | } 184 | -------------------------------------------------------------------------------- /src/options.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_OPTIONS_H 28 | #define ICMPTUNNEL_OPTIONS_H 29 | 30 | struct options 31 | { 32 | /* interval between keep-alive packets. */ 33 | int keepalive; 34 | 35 | /* number of retries before timing out. */ 36 | int retries; 37 | 38 | /* tunnel mtu. */ 39 | int mtu; 40 | 41 | /* enable windows ping emulation. */ 42 | int emulation; 43 | 44 | /* run as a daemon. */ 45 | int daemon; 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/peer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN PEER WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_PEER_H 28 | #define ICMPTUNNEL_PEER_H 29 | 30 | #include 31 | #include "config.h" 32 | 33 | struct peer 34 | { 35 | int connected; 36 | 37 | /* link address. */ 38 | uint32_t linkip; 39 | 40 | /* next icmp id and sequence numbers. */ 41 | uint16_t nextid; 42 | uint16_t nextseq; 43 | 44 | /* punch-thru sequence numbers. */ 45 | uint16_t punchthru[ICMPTUNNEL_PUNCHTHRU_WINDOW]; 46 | uint16_t nextpunchthru; 47 | uint16_t nextpunchthru_write; 48 | 49 | /* number of timeout intervals since last activity. */ 50 | int seconds; 51 | int timeouts; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/protocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_PROTOCOL_H 28 | #define ICMPTUNNEL_PROTOCOL_H 29 | 30 | #include 31 | 32 | /* magic value used to mark icmp tunnel packets. */ 33 | #define PACKET_MAGIC "TUNL" 34 | 35 | enum PACKET_TYPE 36 | { 37 | PACKET_CONNECTION_REQUEST, 38 | PACKET_CONNECTION_ACCEPT, 39 | PACKET_SERVER_FULL, 40 | PACKET_DATA, 41 | PACKET_PUNCHTHRU, 42 | PACKET_KEEP_ALIVE 43 | }; 44 | 45 | struct packet_header 46 | { 47 | uint8_t magic[4]; 48 | uint8_t type; 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/resolve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "resolve.h" 32 | 33 | int resolve(const char *hostname, uint32_t *address) 34 | { 35 | /* try to interpret the hostname as an ip address. */ 36 | *address = ntohl(inet_addr(hostname)); 37 | 38 | /* if we don't have an ip address, look up the name in dns. */ 39 | if (*address == INADDR_NONE) { 40 | struct hostent *h = gethostbyname(hostname); 41 | 42 | if (!h) { 43 | fprintf(stderr, "unable to resolve: %s\n", hostname); 44 | return 1; 45 | } 46 | 47 | *address = ntohl(*(uint32_t*)h->h_addr_list[0]); 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /src/resolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_RESOLVE_H 28 | #define ICMPTUNNEL_RESOLVE_H 29 | 30 | #include 31 | 32 | /* resolve a hostname. */ 33 | int resolve(const char *hostname, uint32_t *address); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/server-handlers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "peer.h" 30 | #include "echo-skt.h" 31 | #include "tun-device.h" 32 | #include "protocol.h" 33 | #include "server-handlers.h" 34 | 35 | void handle_connection_request(struct echo_skt *skt, struct peer *client, 36 | struct echo *request, uint32_t sourceip) 37 | { 38 | struct packet_header *header = (struct packet_header*)skt->data; 39 | memcpy(header->magic, PACKET_MAGIC, sizeof(struct packet_header)); 40 | 41 | /* is a client already connected? */ 42 | if (client->connected) { 43 | header->type = PACKET_SERVER_FULL; 44 | } 45 | else { 46 | header->type = PACKET_CONNECTION_ACCEPT; 47 | 48 | client->connected = 1; 49 | client->seconds = 0; 50 | client->timeouts = 0; 51 | client->nextpunchthru = 0; 52 | client->nextpunchthru_write = 0; 53 | client->linkip = sourceip; 54 | } 55 | 56 | /* send the response. */ 57 | struct echo response; 58 | response.size = sizeof(struct packet_header); 59 | response.reply = 1; 60 | response.id = request->id; 61 | response.seq = request->seq; 62 | 63 | send_echo(skt, sourceip, &response); 64 | } 65 | 66 | /* handle a punch-thru packet. */ 67 | void handle_punchthru(struct peer *client, struct echo *request, uint32_t sourceip) 68 | { 69 | if (!client->connected || sourceip != client->linkip) 70 | return; 71 | 72 | /* store the sequence number. */ 73 | client->punchthru[client->nextpunchthru_write] = request->seq; 74 | client->nextpunchthru_write++; 75 | client->nextpunchthru_write %= ICMPTUNNEL_PUNCHTHRU_WINDOW; 76 | 77 | client->seconds = 0; 78 | client->timeouts = 0; 79 | } 80 | 81 | void handle_keep_alive_request(struct echo_skt *skt, struct peer *client, struct echo *request, 82 | uint32_t sourceip) 83 | { 84 | if (!client->connected || sourceip != client->linkip) 85 | return; 86 | 87 | /* write a keep-alive response. */ 88 | struct packet_header *header = (struct packet_header*)skt->data; 89 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 90 | header->type = PACKET_KEEP_ALIVE; 91 | 92 | /* send the response to the client. */ 93 | struct echo response; 94 | response.size = sizeof(struct packet_header); 95 | response.reply = 1; 96 | response.id = request->id; 97 | response.seq = request->seq; 98 | 99 | send_echo(skt, sourceip, &response); 100 | 101 | client->timeouts = 0; 102 | } 103 | 104 | void handle_server_data(struct echo_skt *skt, struct tun_device *device, struct peer *client, 105 | struct echo *request, uint32_t sourceip) 106 | { 107 | if (!client->connected || sourceip != client->linkip) 108 | return; 109 | 110 | /* determine the size of the encapsulated frame. */ 111 | int framesize = request->size - sizeof(struct packet_header); 112 | 113 | if (!framesize) 114 | return; 115 | 116 | /* write the frame to the tunnel interface. */ 117 | write_tun_device(device, skt->data + sizeof(struct packet_header), framesize); 118 | 119 | /* save the icmp id and sequence numbers for any return traffic. */ 120 | client->nextid = request->id; 121 | client->nextseq = request->seq; 122 | client->seconds = 0; 123 | client->timeouts = 0; 124 | } 125 | -------------------------------------------------------------------------------- /src/server-handlers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_SERVER_HANDLERS_H 28 | #define ICMPTUNNEL_SERVER_HANDLERS_H 29 | 30 | struct peer; 31 | struct echo; 32 | struct echo_skt; 33 | 34 | /* handle a connection request packet. */ 35 | void handle_connection_request(struct echo_skt *skt, struct peer *client, struct echo *request, 36 | uint32_t sourceip); 37 | 38 | /* handle a punch-thru packet. */ 39 | void handle_punchthru(struct peer *client, struct echo *request, uint32_t sourceip); 40 | 41 | /* handle a keep-alive request packet. */ 42 | void handle_keep_alive_request(struct echo_skt *skt, struct peer *client, struct echo *request, 43 | uint32_t sourceip); 44 | 45 | /* handle a data packet. */ 46 | void handle_server_data(struct echo_skt *skt, struct tun_device *devuce, struct peer *client, 47 | struct echo *request, uint32_t sourceip); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "config.h" 31 | #include "daemon.h" 32 | #include "options.h" 33 | #include "server.h" 34 | #include "peer.h" 35 | #include "protocol.h" 36 | #include "echo-skt.h" 37 | #include "tun-device.h" 38 | #include "handlers.h" 39 | #include "forwarder.h" 40 | #include "server-handlers.h" 41 | 42 | /* the client. */ 43 | static struct peer client; 44 | 45 | /* program options. */ 46 | static struct options *opts; 47 | 48 | /* handle an icmp packet. */ 49 | static void handle_icmp_packet(struct echo_skt *skt, struct tun_device *device); 50 | 51 | /* handle data from the tunnel interface. */ 52 | static void handle_tunnel_data(struct echo_skt *skt, struct tun_device *device); 53 | 54 | /* handle a timeout. */ 55 | static void handle_timeout(struct echo_skt *skt); 56 | 57 | int server(struct options *options) 58 | { 59 | struct echo_skt skt; 60 | struct tun_device device; 61 | 62 | struct handlers handlers = { 63 | &handle_icmp_packet, 64 | &handle_tunnel_data, 65 | &handle_timeout 66 | }; 67 | opts = options; 68 | 69 | /* calculate the required icmp payload size. */ 70 | int bufsize = options->mtu + sizeof(struct packet_header); 71 | 72 | /* open an echo socket. */ 73 | if (open_echo_skt(&skt, bufsize) != 0) 74 | return 1; 75 | 76 | /* open a tunnel interface. */ 77 | if (open_tun_device(&device, options->mtu) != 0) 78 | return 1; 79 | 80 | /* fork and run as a daemon if needed. */ 81 | if (options->daemon) { 82 | if (daemon() != 0) 83 | return 1; 84 | } 85 | 86 | /* run the packet forwarding loop. */ 87 | int ret = forward(&skt, &device, &handlers); 88 | 89 | close_tun_device(&device); 90 | close_echo_skt(&skt); 91 | 92 | return ret; 93 | } 94 | 95 | void handle_icmp_packet(struct echo_skt *skt, struct tun_device *device) 96 | { 97 | struct echo echo; 98 | uint32_t sourceip; 99 | 100 | /* receive the packet. */ 101 | if (receive_echo(skt, &sourceip, &echo) != 0) 102 | return; 103 | 104 | /* we're only expecting echo requests. */ 105 | if (echo.reply) 106 | return; 107 | 108 | /* check the packet size. */ 109 | if (echo.size < (int)sizeof(struct packet_header)) 110 | return; 111 | 112 | /* check the header magic. */ 113 | struct packet_header *header = (struct packet_header*)skt->data; 114 | 115 | if (memcmp(header->magic, PACKET_MAGIC, sizeof(header->magic)) != 0) 116 | return; 117 | 118 | switch (header->type) { 119 | case PACKET_CONNECTION_REQUEST: 120 | /* handle a connection request packet. */ 121 | handle_connection_request(skt, &client, &echo, sourceip); 122 | break; 123 | 124 | case PACKET_DATA: 125 | /* handle a data packet. */ 126 | handle_server_data(skt, device, &client, &echo, sourceip); 127 | break; 128 | 129 | case PACKET_PUNCHTHRU: 130 | /* handle a punch-thru packet. */ 131 | handle_punchthru(&client, &echo, sourceip); 132 | break; 133 | 134 | case PACKET_KEEP_ALIVE: 135 | /* handle a keep-alive request packet. */ 136 | handle_keep_alive_request(skt, &client, &echo, sourceip); 137 | break; 138 | } 139 | } 140 | 141 | void handle_tunnel_data(struct echo_skt *skt, struct tun_device *device) 142 | { 143 | int size; 144 | 145 | /* read the frame. */ 146 | if (read_tun_device(device, skt->data + sizeof(struct packet_header), &size) != 0) 147 | return; 148 | 149 | /* if no client is connected then drop the frame. */ 150 | if (!client.connected) 151 | return; 152 | 153 | /* write a data packet. */ 154 | struct packet_header *header = (struct packet_header*)skt->data; 155 | memcpy(header->magic, PACKET_MAGIC, sizeof(header->magic)); 156 | header->type = PACKET_DATA; 157 | 158 | /* send the encapsulated frame to the client. */ 159 | struct echo echo; 160 | echo.size = sizeof(struct packet_header) + size; 161 | echo.reply = 1; 162 | echo.id = client.nextid; 163 | echo.seq = client.punchthru[client.nextpunchthru]; 164 | 165 | client.nextpunchthru++; 166 | client.nextpunchthru %= ICMPTUNNEL_PUNCHTHRU_WINDOW; 167 | 168 | send_echo(skt, client.linkip, &echo); 169 | } 170 | 171 | void handle_timeout(struct echo_skt *skt) 172 | { 173 | /* unused parameter. */ 174 | (void)skt; 175 | 176 | if (!client.connected) 177 | return; 178 | 179 | /* has the peer timeout elapsed? */ 180 | if (++client.seconds == opts->keepalive) { 181 | client.seconds = 0; 182 | 183 | /* have we reached the max number of retries? */ 184 | if (opts->retries != -1 && ++client.timeouts == opts->retries) { 185 | fprintf(stderr, "client connection timed out.\n"); 186 | 187 | client.connected = 0; 188 | return; 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_SERVER_H 28 | #define ICMPTUNNEL_SERVER_H 29 | 30 | struct options; 31 | 32 | /* run the server. */ 33 | int server(struct options *options); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/tun-device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "tun-device.h" 37 | 38 | int open_tun_device(struct tun_device *device, int mtu) 39 | { 40 | struct ifreq ifr; 41 | const char *clonedev = "/dev/net/tun"; 42 | 43 | /* open the clone device. */ 44 | if ((device->fd = open(clonedev, O_RDWR)) < 0) { 45 | fprintf(stderr, "unable to open %s: %s\n", clonedev, strerror(errno)); 46 | fprintf(stderr, "is the tun kernel module loaded?\n"); 47 | return 1; 48 | } 49 | 50 | memset(&ifr, 0, sizeof(ifr)); 51 | ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 52 | 53 | /* try to create the device, the kernel will choose a name. */ 54 | if (ioctl(device->fd, TUNSETIFF, &ifr) < 0) { 55 | fprintf(stderr, "unable to create a tunnel device: %s\n", strerror(errno)); 56 | return 1; 57 | } 58 | 59 | /* copy out the device name and mtu. */ 60 | strncpy(device->name, ifr.ifr_name, sizeof(device->name)); 61 | device->mtu = mtu; 62 | 63 | fprintf(stderr, "opened tunnel device: %s\n", ifr.ifr_name); 64 | 65 | return 0; 66 | } 67 | 68 | int write_tun_device(struct tun_device *device, const char *buf, int size) 69 | { 70 | /* write to the tunnel device. */ 71 | if (write(device->fd, buf, size) != size) { 72 | fprintf(stderr, "unable to write to tunnel device: %s\n", strerror(errno)); 73 | return 1; 74 | } 75 | 76 | return 0; 77 | } 78 | 79 | int read_tun_device(struct tun_device *device, char *buf, int *size) 80 | { 81 | /* read from the tunnel device. */ 82 | if ((*size = read(device->fd, buf, device->mtu)) < 0) { 83 | fprintf(stderr, "unable to read from tunnel device: %s\n", strerror(errno)); 84 | return 1; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | void close_tun_device(struct tun_device *device) 91 | { 92 | if (device->fd >= 0) { 93 | close(device->fd); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/tun-device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/jamesbarlow/icmptunnel 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 James Barlow-Bignell 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef ICMPTUNNEL_TUN_DEVICE_H 28 | #define ICMPTUNNEL_TUN_DEVICE_H 29 | 30 | #include 31 | #include 32 | 33 | struct tun_device 34 | { 35 | int fd; 36 | int mtu; 37 | char name[20]; 38 | }; 39 | 40 | /* open a virtual tunnel device. */ 41 | int open_tun_device(struct tun_device *device, int mtu); 42 | 43 | /* write to the device. */ 44 | int write_tun_device(struct tun_device *device, const char *buf, int size); 45 | 46 | /* read from the device. */ 47 | int read_tun_device(struct tun_device *device, char *buf, int *size); 48 | 49 | /* close the device. */ 50 | void close_tun_device(struct tun_device *device); 51 | 52 | #endif 53 | --------------------------------------------------------------------------------