helper to install firewall rules to hijack all DNS traffic and send it to our virtual interface (except for DNS traffic that originates on the specified port). More...
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_common.h"
#include "gnunet_protocols.h"
Go to the source code of this file.
Data Structures | |
struct | in6_ifreq |
This is in linux/include/net/ipv6.h, but not always exported... More... | |
Macros | |
#define | MAX_SIZE 65536 |
Need 'struct GNUNET_MessageHeader'. More... | |
#define | DNS_PORT "53" |
Port for DNS traffic. More... | |
#define | DNS_MARK "136708149" |
Marker we set for our hijacked DNS traffic. More... | |
#define | DNS_TABLE "53" |
Table we use for our DNS rules. More... | |
Functions | |
static void | signal_handler (int signal) |
Signal handler called to initiate "nice" shutdown. More... | |
static void | open_dev_null (int target_fd, int flags) |
Open '/dev/null' and make the result the given file descriptor. More... | |
static int | fork_and_exec (const char *file, const char *const cmd[]) |
Run the given command and wait for it to complete. More... | |
static int | init_tun (char *dev) |
Creates a tun-interface called dev;. More... | |
static void | set_address6 (const char *dev, const char *address, unsigned long prefix_len) |
Sets the IPv6-Address given in address on the interface dev. More... | |
static void | set_address4 (const char *dev, const char *address, const char *mask) |
Sets the IPv4-Address given in address on the interface dev. More... | |
static void | run (int fd_tun) |
Start forwarding to and from the tunnel. More... | |
int | main (int argc, char *const *argv) |
Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, redirects all outgoing DNS traffic (except from the specified port) to that interface and then passes traffic from and to the interface via stdin/stdout. More... | |
Variables | |
static const char * | sbin_iptables |
Name and full path of IPTABLES binary. More... | |
static const char * | sbin_ip6tables |
Name and full path of IPTABLES binary. More... | |
static const char * | sbin_sysctl |
Name and full path of sysctl binary. More... | |
static const char * | sbin_ip |
Name and full path of IPTABLES binary. More... | |
static int | cpipe [2] |
Control pipe for shutdown via signal. More... | |
helper to install firewall rules to hijack all DNS traffic and send it to our virtual interface (except for DNS traffic that originates on the specified port).
We then allow interacting with our virtual interface via stdin/stdout.
This program alters the Linux firewall rules so that DNS traffic that ordinarily exits the system can be intercepted and managed by a virtual interface. In order to achieve this, DNS traffic is marked with the DNS_MARK given in below and re-routed to a custom table with the DNS_TABLE ID given below. Systems and administrators must take care to not cause conflicts with these values (it was deemed safest to hardcode them as passing these values as arguments might permit messing with arbitrary firewall rules, which would be dangerous). Traffic coming from the same group ID as the effective group ID that this process is running as is not intercepted.
The code first sets up the virtual interface, then begins to redirect the DNS traffic to it, and then on errors or SIGTERM shuts down the virtual interface and removes the rules for the traffic redirection.
Note that having this binary SUID is only partially safe: it will allow redirecting (and intercepting / mangling) of all DNS traffic originating from this system by any user who is able to run it. Furthermore, this code will make it trivial to DoS all DNS traffic originating from the current system, simply by sending it to nowhere (redirect stdout to /dev/null).
Naturally, neither of these problems can be helped as this is the fundamental purpose of the binary. Certifying that this code is "safe" thus only means that it doesn't allow anything else (such as local priv. escalation, etc.).
The following list of people have reviewed this code and considered it safe (within specifications) since the last modification (if you reviewed it, please have your name added to the list):
Definition in file gnunet-helper-dns.c.
#define MAX_SIZE 65536 |
Need 'struct GNUNET_MessageHeader'.
Need DNS message types. Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
Definition at line 86 of file gnunet-helper-dns.c.
#define DNS_PORT "53" |
Port for DNS traffic.
Definition at line 123 of file gnunet-helper-dns.c.
#define DNS_MARK "136708149" |
Marker we set for our hijacked DNS traffic.
We use GNUnet's port (2086) plus the DNS port (53) in HEX to make a 32-bit mark (which is hopefully long enough to not collide); so 0x08260035 = 136708149 (hopefully unique enough...).
Definition at line 131 of file gnunet-helper-dns.c.
#define DNS_TABLE "53" |
Table we use for our DNS rules.
0-255 is the range and 0, 253, 254 and 255 are already reserved. As this is about DNS and as "53" is likely (fingers crossed!) high enough to not usually conflict with a normal user's setup, we use 53 to give a hint that this has something to do with DNS.
Definition at line 140 of file gnunet-helper-dns.c.
|
static |
Signal handler called to initiate "nice" shutdown.
Signals select loop via non-bocking pipe 'cpipe'.
signal | signal number of the signal (not used) |
Definition at line 157 of file gnunet-helper-dns.c.
References cpipe.
Referenced by main().
|
static |
Open '/dev/null' and make the result the given file descriptor.
target_fd | desired FD to point to /dev/null |
flags | open flags (O_RDONLY, O_WRONLY) |
Definition at line 173 of file gnunet-helper-dns.c.
Referenced by fork_and_exec().
|
static |
Run the given command and wait for it to complete.
file | name of the binary to run |
cmd | command line arguments (as given to 'execv') |
Definition at line 200 of file gnunet-helper-dns.c.
References open_dev_null(), pid, ret, and status.
Referenced by main().
|
static |
Creates a tun-interface called dev;.
dev | is assumed to point to a char[IFNAMSIZ] if *dev == '\0', uses the name supplied by the kernel; |
Definition at line 258 of file gnunet-helper-dns.c.
Referenced by main().
|
static |
Sets the IPv6-Address given in address on the interface dev.
dev | the interface to configure |
address | the IPv6-Address |
prefix_len | the length of the network-prefix |
Definition at line 309 of file gnunet-helper-dns.c.
References address, in6_ifreq::ifr6_addr, in6_ifreq::ifr6_ifindex, and in6_ifreq::ifr6_prefixlen.
Referenced by main().
|
static |
Sets the IPv4-Address given in address on the interface dev.
dev | the interface to configure |
address | the IPv4-Address |
mask | the netmask |
Definition at line 406 of file gnunet-helper-dns.c.
References address.
Referenced by main().
|
static |
Start forwarding to and from the tunnel.
This function runs with "reduced" privileges (saved UID is still 0, but effective UID is the real user ID).
fd_tun | tunnel FD |
Definition at line 511 of file gnunet-helper-dns.c.
References cpipe, GNUNET_MESSAGE_TYPE_DNS_HELPER, max, MAX_SIZE, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.
Referenced by main().
int main | ( | int | argc, |
char *const * | argv | ||
) |
Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, redirects all outgoing DNS traffic (except from the specified port) to that interface and then passes traffic from and to the interface via stdin/stdout.
Once stdin/stdout close or have other errors, the tunnel is closed and the DNS traffic redirection is stopped.
argc | number of arguments |
argv | 0: binary name (should be "gnunet-helper-vpn") 1: tunnel interface name (typically "gnunet-dns") 2: IPv6 address for the tunnel ("FE80::1") 3: IPv6 netmask length in bits ("64") 4: IPv4 address for the tunnel ("1.2.3.4") 5: IPv4 netmask ("255.255.0.0") 6: skip sysctl, routing and iptables setup ("0") |
Definition at line 739 of file gnunet-helper-dns.c.
References address, cpipe, DNS_MARK, DNS_PORT, DNS_TABLE, fork_and_exec(), GNUNET_TERM_SIG, init_tun(), run(), sbin_ip, sbin_ip6tables, sbin_iptables, sbin_sysctl, set_address4(), set_address6(), and signal_handler().
|
static |
Name and full path of IPTABLES binary.
Definition at line 103 of file gnunet-helper-dns.c.
Referenced by main().
|
static |
Name and full path of IPTABLES binary.
Definition at line 108 of file gnunet-helper-dns.c.
Referenced by main().
|
static |
Name and full path of sysctl binary.
Definition at line 113 of file gnunet-helper-dns.c.
Referenced by main().
|
static |
Name and full path of IPTABLES binary.
Definition at line 118 of file gnunet-helper-dns.c.
|
static |
Control pipe for shutdown via signal.
[0] is the read end, [1] is the write end.
Definition at line 147 of file gnunet-helper-dns.c.
Referenced by main(), run(), and signal_handler().