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