1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 #include <arpa/inet.h> 22 #include <netinet/in.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 25 #include <sys/stat.h> 26 #include <sys/types.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 30 #ifdef __linux__ 31 32 // There are several ways to play with this program. Here we just give an 33 // example for the simplest scenario. Let us say that a Linux box has a 34 // public IPv4 address on eth0. Please try the following steps and adjust 35 // the parameters when necessary. 36 // 37 // # Enable IP forwarding 38 // echo 1 > /proc/sys/net/ipv4/ip_forward 39 // 40 // # Pick a range of private addresses and perform NAT over eth0. 41 // iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE 42 // 43 // # Create a TUN interface. 44 // ip tuntap add dev tun0 mode tun 45 // 46 // # Set the addresses and bring up the interface. 47 // ifconfig tun0 10.0.0.1 dstaddr 10.0.0.2 up 48 // 49 // # Create a server on port 8000 with shared secret "test". 50 // ./ToyVpnServer tun0 8000 test -m 1400 -a 10.0.0.2 32 -d 8.8.8.8 -r 0.0.0.0 0 51 // 52 // This program only handles a session at a time. To allow multiple sessions, 53 // multiple servers can be created on the same port, but each of them requires 54 // its own TUN interface. A short shell script will be sufficient. Since this 55 // program is designed for demonstration purpose, it performs neither strong 56 // authentication nor encryption. DO NOT USE IT IN PRODUCTION! 57 58 #include <net/if.h> 59 #include <linux/if_tun.h> 60 61 static int get_interface(char *name) 62 { 63 int interface = open("/dev/net/tun", O_RDWR | O_NONBLOCK); 64 65 ifreq ifr; 66 memset(&ifr, 0, sizeof(ifr)); 67 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 68 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 69 70 if (ioctl(interface, TUNSETIFF, &ifr)) { 71 perror("Cannot get TUN interface"); 72 exit(1); 73 } 74 75 return interface; 76 } 77 78 #else 79 80 #error Sorry, you have to implement this part by yourself. 81 82 #endif 83 84 static int get_tunnel(char *port, char *secret) 85 { 86 // We use an IPv6 socket to cover both IPv4 and IPv6. 87 int tunnel = socket(AF_INET6, SOCK_DGRAM, 0); 88 int flag = 1; 89 setsockopt(tunnel, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 90 flag = 0; 91 setsockopt(tunnel, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)); 92 93 // Accept packets received on any local address. 94 sockaddr_in6 addr; 95 memset(&addr, 0, sizeof(addr)); 96 addr.sin6_family = AF_INET6; 97 addr.sin6_port = htons(atoi(port)); 98 99 // Call bind(2) in a loop since Linux does not have SO_REUSEPORT. 100 while (bind(tunnel, (sockaddr *)&addr, sizeof(addr))) { 101 if (errno != EADDRINUSE) { 102 return -1; 103 } 104 usleep(100000); 105 } 106 107 // Receive packets till the secret matches. 108 char packet[1024]; 109 socklen_t addrlen; 110 do { 111 addrlen = sizeof(addr); 112 int n = recvfrom(tunnel, packet, sizeof(packet), 0, 113 (sockaddr *)&addr, &addrlen); 114 if (n <= 0) { 115 return -1; 116 } 117 packet[n] = 0; 118 } while (packet[0] != 0 || strcmp(secret, &packet[1])); 119 120 // Connect to the client as we only handle one client at a time. 121 connect(tunnel, (sockaddr *)&addr, addrlen); 122 return tunnel; 123 } 124 125 static void build_parameters(char *parameters, int size, int argc, char **argv) 126 { 127 // Well, for simplicity, we just concatenate them (almost) blindly. 128 int offset = 0; 129 for (int i = 4; i < argc; ++i) { 130 char *parameter = argv[i]; 131 int length = strlen(parameter); 132 char delimiter = ','; 133 134 // If it looks like an option, prepend a space instead of a comma. 135 if (length == 2 && parameter[0] == '-') { 136 ++parameter; 137 --length; 138 delimiter = ' '; 139 } 140 141 // This is just a demo app, really. 142 if (offset + length >= size) { 143 puts("Parameters are too large"); 144 exit(1); 145 } 146 147 // Append the delimiter and the parameter. 148 parameters[offset] = delimiter; 149 memcpy(¶meters[offset + 1], parameter, length); 150 offset += 1 + length; 151 } 152 153 // Fill the rest of the space with spaces. 154 memset(¶meters[offset], ' ', size - offset); 155 156 // Control messages always start with zero. 157 parameters[0] = 0; 158 } 159 160 //----------------------------------------------------------------------------- 161 162 int main(int argc, char **argv) 163 { 164 if (argc < 5) { 165 printf("Usage: %s <tunN> <port> <secret> options...\n" 166 "\n" 167 "Options:\n" 168 " -m <MTU> for the maximum transmission unit\n" 169 " -a <address> <prefix-length> for the private address\n" 170 " -r <address> <prefix-length> for the forwarding route\n" 171 " -d <address> for the domain name server\n" 172 " -s <domain> for the search domain\n" 173 "\n" 174 "Note that TUN interface needs to be configured properly\n" 175 "BEFORE running this program. For more information, please\n" 176 "read the comments in the source code.\n\n", argv[0]); 177 exit(1); 178 } 179 180 // Parse the arguments and set the parameters. 181 char parameters[1024]; 182 build_parameters(parameters, sizeof(parameters), argc, argv); 183 184 // Get TUN interface. 185 int interface = get_interface(argv[1]); 186 187 // Wait for a tunnel. 188 int tunnel; 189 while ((tunnel = get_tunnel(argv[2], argv[3])) != -1) { 190 printf("%s: Here comes a new tunnel\n", argv[1]); 191 192 // On UN*X, there are many ways to deal with multiple file 193 // descriptors, such as poll(2), select(2), epoll(7) on Linux, 194 // kqueue(2) on FreeBSD, pthread(3), or even fork(2). Here we 195 // mimic everything from the client, so their source code can 196 // be easily compared side by side. 197 198 // Put the tunnel into non-blocking mode. 199 fcntl(tunnel, F_SETFL, O_NONBLOCK); 200 201 // Send the parameters several times in case of packet loss. 202 for (int i = 0; i < 3; ++i) { 203 send(tunnel, parameters, sizeof(parameters), MSG_NOSIGNAL); 204 } 205 206 // Allocate the buffer for a single packet. 207 char packet[32767]; 208 209 // We use a timer to determine the status of the tunnel. It 210 // works on both sides. A positive value means sending, and 211 // any other means receiving. We start with receiving. 212 int timer = 0; 213 214 // We keep forwarding packets till something goes wrong. 215 while (true) { 216 // Assume that we did not make any progress in this iteration. 217 bool idle = true; 218 219 // Read the outgoing packet from the input stream. 220 int length = read(interface, packet, sizeof(packet)); 221 if (length > 0) { 222 // Write the outgoing packet to the tunnel. 223 send(tunnel, packet, length, MSG_NOSIGNAL); 224 225 // There might be more outgoing packets. 226 idle = false; 227 228 // If we were receiving, switch to sending. 229 if (timer < 1) { 230 timer = 1; 231 } 232 } 233 234 // Read the incoming packet from the tunnel. 235 length = recv(tunnel, packet, sizeof(packet), 0); 236 if (length == 0) { 237 break; 238 } 239 if (length > 0) { 240 // Ignore control messages, which start with zero. 241 if (packet[0] != 0) { 242 // Write the incoming packet to the output stream. 243 write(interface, packet, length); 244 } 245 246 // There might be more incoming packets. 247 idle = false; 248 249 // If we were sending, switch to receiving. 250 if (timer > 0) { 251 timer = 0; 252 } 253 } 254 255 // If we are idle or waiting for the network, sleep for a 256 // fraction of time to avoid busy looping. 257 if (idle) { 258 usleep(100000); 259 260 // Increase the timer. This is inaccurate but good enough, 261 // since everything is operated in non-blocking mode. 262 timer += (timer > 0) ? 100 : -100; 263 264 // We are receiving for a long time but not sending. 265 // Can you figure out why we use a different value? :) 266 if (timer < -16000) { 267 // Send empty control messages. 268 packet[0] = 0; 269 for (int i = 0; i < 3; ++i) { 270 send(tunnel, packet, 1, MSG_NOSIGNAL); 271 } 272 273 // Switch to sending. 274 timer = 1; 275 } 276 277 // We are sending for a long time but not receiving. 278 if (timer > 20000) { 279 break; 280 } 281 } 282 } 283 printf("%s: The tunnel is broken\n", argv[1]); 284 close(tunnel); 285 } 286 perror("Cannot create tunnels"); 287 exit(1); 288 } 289