aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-14 20:58:36 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-14 20:58:36 +0000
commit4f285bb38af149f35a1bd3e730ac6bac7b14fd53 (patch)
tree690774a9d24d61f7713f38ca3574d0b620ff661b /src
parentc1e66b2a4e2ccf3fc4f3396d97254fa058c6ae73 (diff)
downloadgnunet-4f285bb38af149f35a1bd3e730ac6bac7b14fd53.tar.gz
gnunet-4f285bb38af149f35a1bd3e730ac6bac7b14fd53.zip
changing exit helper code to automatically do the network configuration for an exit node (by running sysctl/iptables commands as necessary)
Diffstat (limited to 'src')
-rw-r--r--src/exit/exit.conf39
-rw-r--r--src/exit/gnunet-daemon-exit.c166
-rw-r--r--src/exit/gnunet-helper-exit.c175
3 files changed, 298 insertions, 82 deletions
diff --git a/src/exit/exit.conf b/src/exit/exit.conf
index 83dfae888..bbf463047 100644
--- a/src/exit/exit.conf
+++ b/src/exit/exit.conf
@@ -1,12 +1,43 @@
1[exit] 1[exit]
2CONFIG = $DEFAULTCONFIG 2CONFIG = $DEFAULTCONFIG
3BINARY = gnunet-daemon-exit 3BINARY = gnunet-daemon-exit
4
5# IPv6 address for the TUN interface (must be changed as this
6# must be within the global IPv6 range of your system!)
4IPV6ADDR = 1234:1::1 7IPV6ADDR = 1234:1::1
8
9# Prefix for our IPv6 subnet on the TUN interface.
5IPV6PREFIX = 32 10IPV6PREFIX = 32
11
12# IPv4 address to use on our TUN interface (may need to be
13# changed to avoid conflicts with existing addresses on your system).
6IPV4ADDR = 10.10.1.1 14IPV4ADDR = 10.10.1.1
15
16# Netmask for the IPv4 subnet on the TUN interface.
7IPV4MASK = 255.255.0.0 17IPV4MASK = 255.255.0.0
8IFNAME = exit-gnunet
9ENABLE_UDP = NO
10ENABLE_TCP = NO
11 18
12# MAX_CONNECTIONS = 256 19
20# Name of the (virtual) tunnel interface the exit daemon will manage
21TUN_IFNAME = exit-gnunet
22
23# Name of the "real" interface that IPv4 traffic from this system will
24# leave from; this is the name of the interface where we need to
25# enable NAT on postrouting (typically something like 'eth0' or 'eth1'
26# or 'wlan0'). Not needed if EXIT_IPv4 is disabled.
27EXIT_IFNAME = eth0
28
29# Set this to YES to allow exiting this system via IPv4 to the Internet
30EXIT_IPV4 = NO
31
32# Set this to YES to allow exiting this system via IPv6 to the Internet
33EXIT_IPV6 = NO
34
35# For IPv4-services offered by this peer, we need to at least enable IPv4
36ENABLE_IPV4 = NO
37
38# For IPv6-services offered by this peer, we need to at least enable IPv6
39ENABLE_IPV6 = NO
40
41
42# Maximum number of concurrent connections this exit supports.
43MAX_CONNECTIONS = 256
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 2f1865714..9552da155 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -278,6 +278,17 @@ static int ipv4_exit;
278static int ipv6_exit; 278static int ipv6_exit;
279 279
280/** 280/**
281 * Do we support IPv4 at all on the TUN interface?
282 */
283static int ipv4_enabled;
284
285/**
286 * Do we support IPv6 at all on the TUN interface?
287 */
288static int ipv6_enabled;
289
290
291/**
281 * Given IP information about a connection, calculate the respective 292 * Given IP information about a connection, calculate the respective
282 * hash we would use for the 'connections_map'. 293 * hash we would use for the 'connections_map'.
283 * 294 *
@@ -1954,7 +1965,8 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1954 GNUNET_APPLICATION_TYPE_END 1965 GNUNET_APPLICATION_TYPE_END
1955 }; 1966 };
1956 unsigned int app_idx; 1967 unsigned int app_idx;
1957 char *ifname; 1968 char *exit_ifname;
1969 char *tun_ifname;
1958 char *ipv6addr; 1970 char *ipv6addr;
1959 char *ipv6prefix_s; 1971 char *ipv6prefix_s;
1960 char *ipv4addr; 1972 char *ipv4addr;
@@ -1963,8 +1975,29 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1963 struct in6_addr v6; 1975 struct in6_addr v6;
1964 1976
1965 cfg = cfg_; 1977 cfg = cfg_;
1966 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4"); 1978 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
1967 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6"); 1979 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6");
1980 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
1981 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6");
1982 if (ipv4_exit && (! ipv4_enabled))
1983 {
1984 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1985 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
1986 ipv4_enabled = GNUNET_YES;
1987 }
1988 if (ipv6_exit && (! ipv6_enabled))
1989 {
1990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1991 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
1992 ipv6_enabled = GNUNET_YES;
1993 }
1994 if (! (ipv4_enabled || ipv6_enabled))
1995 {
1996 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1997 _("No useful service enabled. Exiting.\n"));
1998 GNUNET_SCHEDULER_shutdown ();
1999 return;
2000 }
1968 app_idx = 0; 2001 app_idx = 0;
1969 if (GNUNET_YES == ipv4_exit) 2002 if (GNUNET_YES == ipv4_exit)
1970 { 2003 {
@@ -1985,68 +2018,101 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1985 max_connections = 1024; 2018 max_connections = 1024;
1986 exit_argv[0] = GNUNET_strdup ("exit-gnunet"); 2019 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1987 if (GNUNET_SYSERR == 2020 if (GNUNET_SYSERR ==
1988 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname)) 2021 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
1989 { 2022 {
1990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2023 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1991 "No entry 'IFNAME' in configuration!\n"); 2024 "No entry 'TUN_IFNAME' in configuration!\n");
1992 GNUNET_SCHEDULER_shutdown (); 2025 GNUNET_SCHEDULER_shutdown ();
1993 return; 2026 return;
1994 } 2027 }
1995 exit_argv[1] = ifname; 2028 exit_argv[1] = tun_ifname;
1996 if ( (GNUNET_SYSERR == 2029 if (ipv4_exit)
1997 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1998 &ipv6addr) ||
1999 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2000 { 2030 {
2001 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2031 if (GNUNET_SYSERR ==
2002 "No valid entry 'IPV6ADDR' in configuration!\n"); 2032 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
2003 GNUNET_SCHEDULER_shutdown (); 2033 {
2004 return; 2034 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2035 "No entry 'EXIT_IFNAME' in configuration!\n");
2036 GNUNET_SCHEDULER_shutdown ();
2037 return;
2038 }
2039 exit_argv[2] = exit_ifname;
2005 } 2040 }
2006 exit_argv[2] = ipv6addr; 2041 else
2007 if (GNUNET_SYSERR ==
2008 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
2009 &ipv6prefix_s))
2010 { 2042 {
2011 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2043 exit_argv[2] = GNUNET_strdup ("%");
2012 "No entry 'IPV6PREFIX' in configuration!\n");
2013 GNUNET_SCHEDULER_shutdown ();
2014 return;
2015 } 2044 }
2016 exit_argv[3] = ipv6prefix_s; 2045 if (GNUNET_YES == ipv6_enabled)
2017 if ( (GNUNET_OK !=
2018 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
2019 "IPV6PREFIX",
2020 &ipv6prefix)) ||
2021 (ipv6prefix >= 127) )
2022 { 2046 {
2023 GNUNET_SCHEDULER_shutdown (); 2047 if ( (GNUNET_SYSERR ==
2024 return; 2048 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
2049 &ipv6addr) ||
2050 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2051 {
2052 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2053 "No valid entry 'IPV6ADDR' in configuration!\n");
2054 GNUNET_SCHEDULER_shutdown ();
2055 return;
2056 }
2057 exit_argv[3] = ipv6addr;
2058 if (GNUNET_SYSERR ==
2059 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
2060 &ipv6prefix_s))
2061 {
2062 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2063 "No entry 'IPV6PREFIX' in configuration!\n");
2064 GNUNET_SCHEDULER_shutdown ();
2065 return;
2066 }
2067 exit_argv[4] = ipv6prefix_s;
2068 if ( (GNUNET_OK !=
2069 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
2070 "IPV6PREFIX",
2071 &ipv6prefix)) ||
2072 (ipv6prefix >= 127) )
2073 {
2074 GNUNET_SCHEDULER_shutdown ();
2075 return;
2076 }
2077 }
2078 else
2079 {
2080 /* IPv6 explicitly disabled */
2081 exit_argv[3] = GNUNET_strdup ("-");
2082 exit_argv[4] = GNUNET_strdup ("-");
2025 } 2083 }
2026 2084 if (GNUNET_YES == ipv4_enabled)
2027 if ( (GNUNET_SYSERR ==
2028 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
2029 &ipv4addr) ||
2030 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2031 { 2085 {
2032 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2086 if ( (GNUNET_SYSERR ==
2033 "No valid entry for 'IPV4ADDR' in configuration!\n"); 2087 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
2034 GNUNET_SCHEDULER_shutdown (); 2088 &ipv4addr) ||
2035 return; 2089 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2090 {
2091 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2092 "No valid entry for 'IPV4ADDR' in configuration!\n");
2093 GNUNET_SCHEDULER_shutdown ();
2094 return;
2095 }
2096 exit_argv[5] = ipv4addr;
2097 if ( (GNUNET_SYSERR ==
2098 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
2099 &ipv4mask) ||
2100 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2101 {
2102 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2103 "No valid entry 'IPV4MASK' in configuration!\n");
2104 GNUNET_SCHEDULER_shutdown ();
2105 return;
2106 }
2107 exit_argv[6] = ipv4mask;
2036 } 2108 }
2037 exit_argv[4] = ipv4addr; 2109 else
2038 if ( (GNUNET_SYSERR ==
2039 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
2040 &ipv4mask) ||
2041 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2042 { 2110 {
2043 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2111 /* IPv4 explicitly disabled */
2044 "No valid entry 'IPV4MASK' in configuration!\n"); 2112 exit_argv[5] = GNUNET_strdup ("-");
2045 GNUNET_SCHEDULER_shutdown (); 2113 exit_argv[6] = GNUNET_strdup ("-");
2046 return;
2047 } 2114 }
2048 exit_argv[5] = ipv4mask; 2115 exit_argv[7] = NULL;
2049 exit_argv[6] = NULL;
2050 2116
2051 udp_services = GNUNET_CONTAINER_multihashmap_create (65536); 2117 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
2052 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536); 2118 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
diff --git a/src/exit/gnunet-helper-exit.c b/src/exit/gnunet-helper-exit.c
index 84b6e6e65..d1db2a6e6 100644
--- a/src/exit/gnunet-helper-exit.c
+++ b/src/exit/gnunet-helper-exit.c
@@ -19,16 +19,21 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file exit/gnunet-helper-exit.c 22 * @file exit/gnunet-helper-exit.c
23 * @brief the helper for exit nodes. Opens a virtual network-interface, 23 *
24 * sends data received on the if to stdout, sends data received on stdin to the 24 * @brief the helper for exit nodes. Opens a virtual
25 * interface 25 * network-interface, sends data received on the if to stdout, sends
26 * @author Philipp Tölke 26 * data received on stdin to the interface. The code also enables
27 * IPv4/IPv6 forwarding and NAT on the current system (the latter on
28 * an interface specified on the command-line); these changes to the
29 * network configuration are NOT automatically undone when the program
30 * is stopped (this is because we cannot be sure that some other
31 * application didn't enable them before or after us; also, these
32 * changes should be mostly harmless as it simply turns the system
33 * into a router).
27 * 34 *
28 * TODO: 35 * @author Philipp Tölke
29 * - need to add code to setup ip_forwarding and NAT (for IPv4) so that 36 * @author Christian Grothoff
30 * users don't need to ALSO do admin work; this is what will set
31 * gnunet-helper-exit.c apart from gnunet-helper-vpn.c
32 * 37 *
33 * The following list of people have reviewed this code and considered 38 * The following list of people have reviewed this code and considered
34 * it safe since the last modification (if you reviewed it, please 39 * it safe since the last modification (if you reviewed it, please
@@ -54,6 +59,17 @@
54 */ 59 */
55#define MAX_SIZE 65536 60#define MAX_SIZE 65536
56 61
62/**
63 * Path to 'sysctl' binary.
64 */
65#define SBIN_SYSCTL "/sbin/sysctl"
66
67/**
68 * Path to 'iptables' binary.
69 */
70#define SBIN_IPTABLES "/sbin/iptables"
71
72
57#ifndef _LINUX_IN6_H 73#ifndef _LINUX_IN6_H
58/** 74/**
59 * This is in linux/include/net/ipv6.h, but not always exported... 75 * This is in linux/include/net/ipv6.h, but not always exported...
@@ -67,6 +83,58 @@ struct in6_ifreq
67#endif 83#endif
68 84
69 85
86
87/**
88 * Run the given command and wait for it to complete.
89 *
90 * @param file name of the binary to run
91 * @param cmd command line arguments (as given to 'execv')
92 * @return 0 on success, 1 on any error
93 */
94static int
95fork_and_exec (const char *file,
96 char *const cmd[])
97{
98 int status;
99 pid_t pid;
100 pid_t ret;
101
102 pid = fork ();
103 if (-1 == pid)
104 {
105 fprintf (stderr,
106 "fork failed: %s\n",
107 strerror (errno));
108 return 1;
109 }
110 if (0 == pid)
111 {
112 /* we are the child process */
113 (void) execv (file, cmd);
114 /* can only get here on error */
115 fprintf (stderr,
116 "exec `%s' failed: %s\n",
117 file,
118 strerror (errno));
119 _exit (1);
120 }
121 /* keep running waitpid as long as the only error we get is 'EINTR' */
122 while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
123 (errno == EINTR) );
124 if (-1 == ret)
125 {
126 fprintf (stderr,
127 "waitpid failed: %s\n",
128 strerror (errno));
129 return 1;
130 }
131 if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
132 return 1;
133 /* child process completed and returned success, we're happy */
134 return 0;
135}
136
137
70/** 138/**
71 * Creates a tun-interface called dev; 139 * Creates a tun-interface called dev;
72 * 140 *
@@ -521,12 +589,13 @@ PROCESS_BUFFER:
521 * Open VPN tunnel interface. 589 * Open VPN tunnel interface.
522 * 590 *
523 * @param argc must be 6 591 * @param argc must be 6
524 * @param argv 0: binary name (gnunet-helper-vpn) 592 * @param argv 0: binary name ("gnunet-helper-vpn")
525 * 1: tunnel interface name (gnunet-vpn) 593 * 1: tunnel interface name ("gnunet-vpn")
526 * 2: IPv6 address (::1) 594 * 2: IPv4 "physical" interface name ("eth0"), or "%" to not do IPv4 NAT
527 * 3: IPv6 netmask length in bits (64) 595 * 3: IPv6 address ("::1"), or "-" to skip IPv6
528 * 4: IPv4 address (1.2.3.4) 596 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
529 * 5: IPv4 netmask (255.255.0.0) 597 * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
598 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
530 */ 599 */
531int 600int
532main (int argc, char **argv) 601main (int argc, char **argv)
@@ -535,11 +604,17 @@ main (int argc, char **argv)
535 int fd_tun; 604 int fd_tun;
536 int global_ret; 605 int global_ret;
537 606
538 if (6 != argc) 607 if (7 != argc)
539 { 608 {
540 fprintf (stderr, "Fatal: must supply 5 arguments!\n"); 609 fprintf (stderr, "Fatal: must supply 5 arguments!\n");
541 return 1; 610 return 1;
542 } 611 }
612 if ( (0 == strcmp (argv[3], "-")) &&
613 (0 == strcmp (argv[5], "-")) )
614 {
615 fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
616 return 1;
617 }
543 618
544 strncpy (dev, argv[1], IFNAMSIZ); 619 strncpy (dev, argv[1], IFNAMSIZ);
545 dev[IFNAMSIZ - 1] = '\0'; 620 dev[IFNAMSIZ - 1] = '\0';
@@ -550,24 +625,66 @@ main (int argc, char **argv)
550 return 1; 625 return 1;
551 } 626 }
552 627
628 if (0 != strcmp (argv[3], "-"))
553 { 629 {
554 const char *address = argv[2];
555 long prefix_len = atol (argv[3]);
556
557 if ((prefix_len < 1) || (prefix_len > 127))
558 { 630 {
559 fprintf (stderr, "Fatal: prefix_len out of range\n"); 631 const char *address = argv[3];
560 return 1; 632 long prefix_len = atol (argv[4]);
633
634 if ((prefix_len < 1) || (prefix_len > 127))
635 {
636 fprintf (stderr, "Fatal: prefix_len out of range\n");
637 return 1;
638 }
639 set_address6 (dev, address, prefix_len);
640 }
641 {
642 char *const sysctl_args[] =
643 {
644 "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
645 };
646 if (0 != fork_and_exec (SBIN_SYSCTL,
647 sysctl_args))
648 {
649 fprintf (stderr,
650 "Failed to enable IPv6 forwarding. Will continue anyway.\n");
651 }
561 } 652 }
562
563 set_address6 (dev, address, prefix_len);
564 } 653 }
565 654
655 if (0 != strcmp (argv[5], "-"))
566 { 656 {
567 const char *address = argv[4]; 657 {
568 const char *mask = argv[5]; 658 const char *address = argv[5];
569 659 const char *mask = argv[6];
570 set_address4 (dev, address, mask); 660
661 set_address4 (dev, address, mask);
662 }
663 {
664 char *const sysctl_args[] =
665 {
666 "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
667 };
668 if (0 != fork_and_exec (SBIN_SYSCTL,
669 sysctl_args))
670 {
671 fprintf (stderr,
672 "Failed to enable IPv4 forwarding. Will continue anyway.\n");
673 }
674 }
675 if (0 != strcmp (argv[2], "%"))
676 {
677 char *const iptables_args[] =
678 {
679 "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
680 };
681 if (0 != fork_and_exec (SBIN_IPTABLES,
682 iptables_args))
683 {
684 fprintf (stderr,
685 "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
686 }
687 }
571 } 688 }
572 689
573 uid_t uid = getuid (); 690 uid_t uid = getuid ();
@@ -599,3 +716,5 @@ main (int argc, char **argv)
599 close (fd_tun); 716 close (fd_tun);
600 return global_ret; 717 return global_ret;
601} 718}
719
720/* end of gnunet-helper-exit.c */