gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r19141 - gnunet/src/exit


From: gnunet
Subject: [GNUnet-SVN] r19141 - gnunet/src/exit
Date: Sat, 14 Jan 2012 21:58:36 +0100

Author: grothoff
Date: 2012-01-14 21:58:36 +0100 (Sat, 14 Jan 2012)
New Revision: 19141

Modified:
   gnunet/src/exit/exit.conf
   gnunet/src/exit/gnunet-daemon-exit.c
   gnunet/src/exit/gnunet-helper-exit.c
Log:
changing exit helper code to automatically do the network configuration for an 
exit node (by running sysctl/iptables commands as necessary)


Modified: gnunet/src/exit/exit.conf
===================================================================
--- gnunet/src/exit/exit.conf   2012-01-14 18:31:25 UTC (rev 19140)
+++ gnunet/src/exit/exit.conf   2012-01-14 20:58:36 UTC (rev 19141)
@@ -1,12 +1,43 @@
 [exit]
 CONFIG = $DEFAULTCONFIG
 BINARY = gnunet-daemon-exit
+
+# IPv6 address for the TUN interface (must be changed as this
+# must be within the global IPv6 range of your system!)
 IPV6ADDR = 1234:1::1
+
+# Prefix for our IPv6 subnet on the TUN interface. 
 IPV6PREFIX = 32
+
+# IPv4 address to use on our TUN interface (may need to be
+# changed to avoid conflicts with existing addresses on your system).
 IPV4ADDR = 10.10.1.1
+
+# Netmask for the IPv4 subnet on the TUN interface.
 IPV4MASK = 255.255.0.0
-IFNAME = exit-gnunet
-ENABLE_UDP = NO
-ENABLE_TCP = NO
 
-# MAX_CONNECTIONS = 256
+
+# Name of the (virtual) tunnel interface the exit daemon will manage
+TUN_IFNAME = exit-gnunet
+
+# Name of the "real" interface that IPv4 traffic from this system will
+# leave from; this is the name of the interface where we need to
+# enable NAT on postrouting (typically something like 'eth0' or 'eth1'
+# or 'wlan0').  Not needed if EXIT_IPv4 is disabled.
+EXIT_IFNAME = eth0
+
+# Set this to YES to allow exiting this system via IPv4 to the Internet
+EXIT_IPV4 = NO
+
+# Set this to YES to allow exiting this system via IPv6 to the Internet
+EXIT_IPV6 = NO
+
+# For IPv4-services offered by this peer, we need to at least enable IPv4
+ENABLE_IPV4 = NO
+
+# For IPv6-services offered by this peer, we need to at least enable IPv6
+ENABLE_IPV6 = NO
+
+
+# Maximum number of concurrent connections this exit supports.
+MAX_CONNECTIONS = 256

Modified: gnunet/src/exit/gnunet-daemon-exit.c
===================================================================
--- gnunet/src/exit/gnunet-daemon-exit.c        2012-01-14 18:31:25 UTC (rev 
19140)
+++ gnunet/src/exit/gnunet-daemon-exit.c        2012-01-14 20:58:36 UTC (rev 
19141)
@@ -278,6 +278,17 @@
 static int ipv6_exit;
 
 /**
+ * Do we support IPv4 at all on the TUN interface?
+ */
+static int ipv4_enabled;
+
+/**
+ * Do we support IPv6 at all on the TUN interface?
+ */
+static int ipv6_enabled;
+
+
+/**
  * Given IP information about a connection, calculate the respective
  * hash we would use for the 'connections_map'.
  *
@@ -1954,7 +1965,8 @@
     GNUNET_APPLICATION_TYPE_END
   };
   unsigned int app_idx;
-  char *ifname;
+  char *exit_ifname;
+  char *tun_ifname;
   char *ipv6addr;
   char *ipv6prefix_s;
   char *ipv4addr;
@@ -1963,8 +1975,29 @@
   struct in6_addr v6;
 
   cfg = cfg_;
-  ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", 
"ENABLE_IPV4");
-  ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", 
"ENABLE_IPV6");
+  ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
+  ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6"); 
+  ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", 
"ENABLE_IPV4");
+  ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", 
"ENABLE_IPV6"); 
+  if (ipv4_exit && (! ipv4_enabled))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, 
will use ENABLE_IPv4=YES\n"));
+    ipv4_enabled = GNUNET_YES;
+  }
+  if (ipv6_exit && (! ipv6_enabled))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, 
will use ENABLE_IPv6=YES\n"));
+    ipv6_enabled = GNUNET_YES;
+  }
+  if (! (ipv4_enabled || ipv6_enabled))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("No useful service enabled.  Exiting.\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;    
+  }
   app_idx = 0;
   if (GNUNET_YES == ipv4_exit)    
   {
@@ -1985,68 +2018,101 @@
     max_connections = 1024;
   exit_argv[0] = GNUNET_strdup ("exit-gnunet");
   if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
+      GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", 
&tun_ifname))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No entry 'IFNAME' in configuration!\n");
+                "No entry 'TUN_IFNAME' in configuration!\n");
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  exit_argv[1] = ifname;
-  if ( (GNUNET_SYSERR ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
-                                              &ipv6addr) ||
-       (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
+  exit_argv[1] = tun_ifname;
+  if (ipv4_exit)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No valid entry 'IPV6ADDR' in configuration!\n");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
+    if (GNUNET_SYSERR ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", 
&exit_ifname))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "No entry 'EXIT_IFNAME' in configuration!\n");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    exit_argv[2] = exit_ifname;
   }
-  exit_argv[2] = ipv6addr;
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
-                                             &ipv6prefix_s))
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No entry 'IPV6PREFIX' in configuration!\n");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
+    exit_argv[2] = GNUNET_strdup ("%");
   }
-  exit_argv[3] = ipv6prefix_s;
-  if ( (GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
-                                              "IPV6PREFIX",
-                                              &ipv6prefix)) ||
-       (ipv6prefix >= 127) )
+  if (GNUNET_YES == ipv6_enabled)
   {
-    GNUNET_SCHEDULER_shutdown ();
-    return;
+    if ( (GNUNET_SYSERR ==
+         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
+                                                &ipv6addr) ||
+         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "No valid entry 'IPV6ADDR' in configuration!\n");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    exit_argv[3] = ipv6addr;
+    if (GNUNET_SYSERR ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
+                                              &ipv6prefix_s))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "No entry 'IPV6PREFIX' in configuration!\n");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    exit_argv[4] = ipv6prefix_s;
+    if ( (GNUNET_OK !=
+         GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
+                                                "IPV6PREFIX",
+                                                &ipv6prefix)) ||
+        (ipv6prefix >= 127) )
+    {
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+  } 
+  else
+  {
+    /* IPv6 explicitly disabled */
+    exit_argv[3] = GNUNET_strdup ("-");
+    exit_argv[4] = GNUNET_strdup ("-");
   }
-
-  if ( (GNUNET_SYSERR ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
-                                              &ipv4addr) ||
-       (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
+  if (GNUNET_YES == ipv4_enabled)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No valid entry for 'IPV4ADDR' in configuration!\n");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
+    if ( (GNUNET_SYSERR ==
+         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
+                                                &ipv4addr) ||
+         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
+      {
+       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                   "No valid entry for 'IPV4ADDR' in configuration!\n");
+       GNUNET_SCHEDULER_shutdown ();
+       return;
+      }
+    exit_argv[5] = ipv4addr;
+    if ( (GNUNET_SYSERR ==
+         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
+                                                &ipv4mask) ||
+         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "No valid entry 'IPV4MASK' in configuration!\n");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    exit_argv[6] = ipv4mask;
   }
-  exit_argv[4] = ipv4addr;
-  if ( (GNUNET_SYSERR ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
-                                              &ipv4mask) ||
-       (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No valid entry 'IPV4MASK' in configuration!\n");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
+    /* IPv4 explicitly disabled */
+    exit_argv[5] = GNUNET_strdup ("-");
+    exit_argv[6] = GNUNET_strdup ("-");
   }
-  exit_argv[5] = ipv4mask;
-  exit_argv[6] = NULL;
+  exit_argv[7] = NULL;
 
   udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
   tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);

Modified: gnunet/src/exit/gnunet-helper-exit.c
===================================================================
--- gnunet/src/exit/gnunet-helper-exit.c        2012-01-14 18:31:25 UTC (rev 
19140)
+++ gnunet/src/exit/gnunet-helper-exit.c        2012-01-14 20:58:36 UTC (rev 
19141)
@@ -19,17 +19,22 @@
 */
 
 /**
- * @file exit/gnunet-helper-exit.c
- * @brief the helper for exit nodes. Opens a virtual network-interface,
- * sends data received on the if to stdout, sends data received on stdin to the
- * interface
+ * @file exit/gnunet-helper-exit.c 
+ *
+ * @brief the helper for exit nodes. Opens a virtual
+ * network-interface, sends data received on the if to stdout, sends
+ * data received on stdin to the interface.  The code also enables
+ * IPv4/IPv6 forwarding and NAT on the current system (the latter on
+ * an interface specified on the command-line); these changes to the
+ * network configuration are NOT automatically undone when the program
+ * is stopped (this is because we cannot be sure that some other
+ * application didn't enable them before or after us; also, these
+ * changes should be mostly harmless as it simply turns the system
+ * into a router).
+ *
  * @author Philipp Tölke
+ * @author Christian Grothoff
  *
- * TODO:
- * - need to add code to setup ip_forwarding and NAT (for IPv4) so that
- *   users don't need to ALSO do admin work; this is what will set
- *   gnunet-helper-exit.c apart from gnunet-helper-vpn.c
- *
  * The following list of people have reviewed this code and considered
  * it safe since the last modification (if you reviewed it, please
  * have your name added to the list):
@@ -54,6 +59,17 @@
  */
 #define MAX_SIZE 65536
 
+/**
+ * Path to 'sysctl' binary.
+ */
+#define SBIN_SYSCTL "/sbin/sysctl"
+
+/**
+ * Path to 'iptables' binary.
+ */
+#define SBIN_IPTABLES "/sbin/iptables"
+
+
 #ifndef _LINUX_IN6_H
 /**
  * This is in linux/include/net/ipv6.h, but not always exported...
@@ -67,7 +83,59 @@
 #endif
 
 
+
 /**
+ * Run the given command and wait for it to complete.
+ * 
+ * @param file name of the binary to run
+ * @param cmd command line arguments (as given to 'execv')
+ * @return 0 on success, 1 on any error
+ */
+static int
+fork_and_exec (const char *file, 
+              char *const cmd[])
+{
+  int status;
+  pid_t pid;
+  pid_t ret;
+
+  pid = fork ();
+  if (-1 == pid)
+  {
+    fprintf (stderr, 
+            "fork failed: %s\n", 
+            strerror (errno));
+    return 1;
+  }
+  if (0 == pid)
+  {
+    /* we are the child process */
+    (void) execv (file, cmd);
+    /* can only get here on error */
+    fprintf (stderr, 
+            "exec `%s' failed: %s\n", 
+            file,
+            strerror (errno));
+    _exit (1);
+  }
+  /* keep running waitpid as long as the only error we get is 'EINTR' */
+  while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
+         (errno == EINTR) ); 
+  if (-1 == ret)
+  {
+    fprintf (stderr, 
+            "waitpid failed: %s\n", 
+            strerror (errno));
+    return 1;
+  }
+  if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
+    return 1;
+  /* child process completed and returned success, we're happy */
+  return 0;
+}
+
+
+/**
  * Creates a tun-interface called dev;
  *
  * @param dev is asumed to point to a char[IFNAMSIZ]
@@ -521,12 +589,13 @@
  * Open VPN tunnel interface.
  *
  * @param argc must be 6
- * @param argv 0: binary name (gnunet-helper-vpn)
- *             1: tunnel interface name (gnunet-vpn)
- *             2: IPv6 address (::1)
- *             3: IPv6 netmask length in bits (64)
- *             4: IPv4 address (1.2.3.4)
- *             5: IPv4 netmask (255.255.0.0)
+ * @param argv 0: binary name ("gnunet-helper-vpn")
+ *             1: tunnel interface name ("gnunet-vpn")
+ *             2: IPv4 "physical" interface name ("eth0"), or "%" to not do 
IPv4 NAT
+ *             3: IPv6 address ("::1"), or "-" to skip IPv6
+ *             4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
+ *             5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
+ *             6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
  */
 int
 main (int argc, char **argv)
@@ -535,11 +604,17 @@
   int fd_tun;
   int global_ret;
 
-  if (6 != argc)
+  if (7 != argc)
   {
     fprintf (stderr, "Fatal: must supply 5 arguments!\n");
     return 1;
   }
+  if ( (0 == strcmp (argv[3], "-")) &&
+       (0 == strcmp (argv[5], "-")) )
+  {
+    fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
+    return 1;
+  }
 
   strncpy (dev, argv[1], IFNAMSIZ);
   dev[IFNAMSIZ - 1] = '\0';
@@ -550,24 +625,66 @@
     return 1;
   }
 
+  if (0 != strcmp (argv[3], "-"))
   {
-    const char *address = argv[2];
-    long prefix_len = atol (argv[3]);
-
-    if ((prefix_len < 1) || (prefix_len > 127))
     {
-      fprintf (stderr, "Fatal: prefix_len out of range\n");
-      return 1;
+      const char *address = argv[3];
+      long prefix_len = atol (argv[4]);
+      
+      if ((prefix_len < 1) || (prefix_len > 127))
+      {
+       fprintf (stderr, "Fatal: prefix_len out of range\n");
+       return 1;
+      }      
+      set_address6 (dev, address, prefix_len);    
     }
-
-    set_address6 (dev, address, prefix_len);
+    {
+      char *const sysctl_args[] =
+       {
+         "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
+       };
+      if (0 != fork_and_exec (SBIN_SYSCTL,
+                             sysctl_args))
+      {
+       fprintf (stderr,
+                "Failed to enable IPv6 forwarding.  Will continue anyway.\n");
+      }    
+    }
   }
 
+  if (0 != strcmp (argv[5], "-"))
   {
-    const char *address = argv[4];
-    const char *mask = argv[5];
-
-    set_address4 (dev, address, mask);
+    {
+      const char *address = argv[5];
+      const char *mask = argv[6];
+      
+      set_address4 (dev, address, mask);
+    }
+    {
+      char *const sysctl_args[] =
+       {
+         "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
+       };
+      if (0 != fork_and_exec (SBIN_SYSCTL,
+                             sysctl_args))
+      {
+       fprintf (stderr,
+                "Failed to enable IPv4 forwarding.  Will continue anyway.\n");
+      }    
+    }
+    if (0 != strcmp (argv[2], "%"))
+    {
+      char *const iptables_args[] =
+       {
+         "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", 
"MASQUERADE", NULL
+       };
+      if (0 != fork_and_exec (SBIN_IPTABLES,
+                             iptables_args))
+      {
+       fprintf (stderr,
+                "Failed to enable IPv4 masquerading (NAT).  Will continue 
anyway.\n");
+      }    
+    }
   }
   
   uid_t uid = getuid ();
@@ -599,3 +716,5 @@
   close (fd_tun);
   return global_ret;
 }
+
+/* end of gnunet-helper-exit.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]