aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dns/Makefile.am1
-rw-r--r--src/dns/dnsstub.c10
-rw-r--r--src/dns/gnunet-helper-dns.c95
-rw-r--r--src/dns/gnunet-service-dns.c8
-rwxr-xr-xsrc/dns/test_gnunet_dns.sh6
-rw-r--r--src/include/gnunet_tun_lib.h14
-rw-r--r--src/tun/tun.c42
7 files changed, 163 insertions, 13 deletions
diff --git a/src/dns/Makefile.am b/src/dns/Makefile.am
index 45b86c71b..f5fcf3782 100644
--- a/src/dns/Makefile.am
+++ b/src/dns/Makefile.am
@@ -89,6 +89,7 @@ libgnunetdnsparser_la_LDFLAGS = \
89libgnunetdnsstub_la_SOURCES = \ 89libgnunetdnsstub_la_SOURCES = \
90 dnsstub.c 90 dnsstub.c
91libgnunetdnsstub_la_LIBADD = \ 91libgnunetdnsstub_la_LIBADD = \
92 $(top_builddir)/src/tun/libgnunettun.la \
92 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) 93 $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
93libgnunetdnsstub_la_LDFLAGS = \ 94libgnunetdnsstub_la_LDFLAGS = \
94 $(GN_LIB_LDFLAGS) \ 95 $(GN_LIB_LDFLAGS) \
diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c
index b3cd2817e..68cd55275 100644
--- a/src/dns/dnsstub.c
+++ b/src/dns/dnsstub.c
@@ -24,6 +24,7 @@
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "gnunet_tun_lib.h"
27#include "gnunet_dnsstub_lib.h" 28#include "gnunet_dnsstub_lib.h"
28 29
29/** 30/**
@@ -381,9 +382,7 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
381 _("Failed to send DNS request to %s\n"), 382 _("Failed to send DNS request to %s\n"),
382 GNUNET_a2s (sa, salen)); 383 GNUNET_a2s (sa, salen));
383 rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); 384 rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
384
385 return rs; 385 return rs;
386
387} 386}
388 387
389 388
@@ -441,9 +440,10 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
441 } 440 }
442 dns = (struct GNUNET_TUN_DnsHeader *) buf; 441 dns = (struct GNUNET_TUN_DnsHeader *) buf;
443 if ( (addrlen != rs->addrlen) || 442 if ( (addrlen != rs->addrlen) ||
444 (0 != memcmp (&rs->addr, 443 (GNUNET_YES !=
445 &addr, 444 GNUNET_TUN_sockaddr_cmp ((struct sockaddr *) &rs->addr,
446 addrlen)) || 445 (struct sockaddr *) &addr,
446 GNUNET_YES)) ||
447 (0 == GNUNET_TIME_absolute_get_remaining (rs->timeout).rel_value_us) ) 447 (0 == GNUNET_TIME_absolute_get_remaining (rs->timeout).rel_value_us) )
448 { 448 {
449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/dns/gnunet-helper-dns.c b/src/dns/gnunet-helper-dns.c
index 2f723d09d..1d411379f 100644
--- a/src/dns/gnunet-helper-dns.c
+++ b/src/dns/gnunet-helper-dns.c
@@ -101,6 +101,11 @@ struct in6_ifreq
101static const char *sbin_iptables; 101static const char *sbin_iptables;
102 102
103/** 103/**
104 * Name and full path of IPTABLES binary.
105 */
106static const char *sbin_ip6tables;
107
108/**
104 * Name and full path of sysctl binary 109 * Name and full path of sysctl binary
105 */ 110 */
106static const char *sbin_sysctl; 111static const char *sbin_sysctl;
@@ -757,7 +762,7 @@ main (int argc, char *const*argv)
757 return 254; 762 return 254;
758 } 763 }
759#endif 764#endif
760 if (0 == strncmp(argv[6], "1", 2)) 765 if (0 == strncmp (argv[6], "1", 2))
761 nortsetup = 1; 766 nortsetup = 1;
762 767
763 if (0 == nortsetup) 768 if (0 == nortsetup)
@@ -774,6 +779,17 @@ main (int argc, char *const*argv)
774 strerror (errno)); 779 strerror (errno));
775 return 3; 780 return 3;
776 } 781 }
782 if (0 == access ("/sbin/ip6tables", X_OK))
783 sbin_ip6tables = "/sbin/ip6tables";
784 else if (0 == access ("/usr/sbin/ip6tables", X_OK))
785 sbin_ip6tables = "/usr/sbin/ip6tables";
786 else
787 {
788 fprintf (stderr,
789 "Fatal: executable ip6tables not found in approved directories: %s\n",
790 strerror (errno));
791 return 3;
792 }
777 if (0 == access ("/sbin/ip", X_OK)) 793 if (0 == access ("/sbin/ip", X_OK))
778 sbin_ip = "/sbin/ip"; 794 sbin_ip = "/sbin/ip";
779 else if (0 == access ("/usr/sbin/ip", X_OK)) 795 else if (0 == access ("/usr/sbin/ip", X_OK))
@@ -942,6 +958,16 @@ main (int argc, char *const*argv)
942 if (0 != fork_and_exec (sbin_iptables, mangle_args)) 958 if (0 != fork_and_exec (sbin_iptables, mangle_args))
943 goto cleanup_rest; 959 goto cleanup_rest;
944 } 960 }
961 {
962 char *const mangle_args[] =
963 {
964 "ip6tables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
965 "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
966 "ACCEPT", NULL
967 };
968 if (0 != fork_and_exec (sbin_ip6tables, mangle_args))
969 goto cleanup_rest;
970 }
945 /* Mark all of the other DNS traffic using our mark DNS_MARK */ 971 /* Mark all of the other DNS traffic using our mark DNS_MARK */
946 { 972 {
947 char *const mark_args[] = 973 char *const mark_args[] =
@@ -953,6 +979,16 @@ main (int argc, char *const*argv)
953 if (0 != fork_and_exec (sbin_iptables, mark_args)) 979 if (0 != fork_and_exec (sbin_iptables, mark_args))
954 goto cleanup_mangle_1; 980 goto cleanup_mangle_1;
955 } 981 }
982 {
983 char *const mark_args[] =
984 {
985 "ip6tables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
986 "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK,
987 NULL
988 };
989 if (0 != fork_and_exec (sbin_ip6tables, mark_args))
990 goto cleanup_mangle_1;
991 }
956 /* Forward all marked DNS traffic to our DNS_TABLE */ 992 /* Forward all marked DNS traffic to our DNS_TABLE */
957 { 993 {
958 char *const forward_args[] = 994 char *const forward_args[] =
@@ -962,6 +998,14 @@ main (int argc, char *const*argv)
962 if (0 != fork_and_exec (sbin_ip, forward_args)) 998 if (0 != fork_and_exec (sbin_ip, forward_args))
963 goto cleanup_mark_2; 999 goto cleanup_mark_2;
964 } 1000 }
1001 {
1002 char *const forward_args[] =
1003 {
1004 "ip", "-6", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1005 };
1006 if (0 != fork_and_exec (sbin_ip, forward_args))
1007 goto cleanup_mark_2;
1008 }
965 /* Finally, add rule in our forwarding table to pass to our virtual interface */ 1009 /* Finally, add rule in our forwarding table to pass to our virtual interface */
966 { 1010 {
967 char *const route_args[] = 1011 char *const route_args[] =
@@ -972,6 +1016,15 @@ main (int argc, char *const*argv)
972 if (0 != fork_and_exec (sbin_ip, route_args)) 1016 if (0 != fork_and_exec (sbin_ip, route_args))
973 goto cleanup_forward_3; 1017 goto cleanup_forward_3;
974 } 1018 }
1019 {
1020 char *const route_args[] =
1021 {
1022 "ip", "-6", "route", "add", "default", "dev", dev,
1023 "table", DNS_TABLE, NULL
1024 };
1025 if (0 != fork_and_exec (sbin_ip, route_args))
1026 goto cleanup_forward_3;
1027 }
975 } 1028 }
976 1029
977 /* drop privs *except* for the saved UID; this is not perfect, but better 1030 /* drop privs *except* for the saved UID; this is not perfect, but better
@@ -1028,6 +1081,16 @@ main (int argc, char *const*argv)
1028 if (0 != fork_and_exec (sbin_ip, route_clean_args)) 1081 if (0 != fork_and_exec (sbin_ip, route_clean_args))
1029 r += 1; 1082 r += 1;
1030 } 1083 }
1084 if (0 == nortsetup)
1085 {
1086 char *const route_clean_args[] =
1087 {
1088 "ip", "-6", "route", "del", "default", "dev", dev,
1089 "table", DNS_TABLE, NULL
1090 };
1091 if (0 != fork_and_exec (sbin_ip, route_clean_args))
1092 r += 1;
1093 }
1031 cleanup_forward_3: 1094 cleanup_forward_3:
1032 if (0 == nortsetup) 1095 if (0 == nortsetup)
1033 { 1096 {
@@ -1038,6 +1101,15 @@ main (int argc, char *const*argv)
1038 if (0 != fork_and_exec (sbin_ip, forward_clean_args)) 1101 if (0 != fork_and_exec (sbin_ip, forward_clean_args))
1039 r += 2; 1102 r += 2;
1040 } 1103 }
1104 if (0 == nortsetup)
1105 {
1106 char *const forward_clean_args[] =
1107 {
1108 "ip", "-6", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1109 };
1110 if (0 != fork_and_exec (sbin_ip, forward_clean_args))
1111 r += 2;
1112 }
1041 cleanup_mark_2: 1113 cleanup_mark_2:
1042 if (0 == nortsetup) 1114 if (0 == nortsetup)
1043 { 1115 {
@@ -1049,6 +1121,16 @@ main (int argc, char *const*argv)
1049 if (0 != fork_and_exec (sbin_iptables, mark_clean_args)) 1121 if (0 != fork_and_exec (sbin_iptables, mark_clean_args))
1050 r += 4; 1122 r += 4;
1051 } 1123 }
1124 if (0 == nortsetup)
1125 {
1126 char *const mark_clean_args[] =
1127 {
1128 "ip6tables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1129 "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL
1130 };
1131 if (0 != fork_and_exec (sbin_ip6tables, mark_clean_args))
1132 r += 4;
1133 }
1052 cleanup_mangle_1: 1134 cleanup_mangle_1:
1053 if (0 == nortsetup) 1135 if (0 == nortsetup)
1054 { 1136 {
@@ -1061,6 +1143,17 @@ main (int argc, char *const*argv)
1061 if (0 != fork_and_exec (sbin_iptables, mangle_clean_args)) 1143 if (0 != fork_and_exec (sbin_iptables, mangle_clean_args))
1062 r += 8; 1144 r += 8;
1063 } 1145 }
1146 if (0 == nortsetup)
1147 {
1148 char *const mangle_clean_args[] =
1149 {
1150 "ip6tables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1151 "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
1152 NULL
1153 };
1154 if (0 != fork_and_exec (sbin_ip6tables, mangle_clean_args))
1155 r += 8;
1156 }
1064 1157
1065 cleanup_rest: 1158 cleanup_rest:
1066 /* close virtual interface */ 1159 /* close virtual interface */
diff --git a/src/dns/gnunet-service-dns.c b/src/dns/gnunet-service-dns.c
index 50aa730e7..52f924cdf 100644
--- a/src/dns/gnunet-service-dns.c
+++ b/src/dns/gnunet-service-dns.c
@@ -410,7 +410,7 @@ request_done (struct RequestRecord *rr)
410 destination_port = src->sin6_port; 410 destination_port = src->sin6_port;
411 GNUNET_TUN_initialize_ipv6_header (&ip6, 411 GNUNET_TUN_initialize_ipv6_header (&ip6,
412 IPPROTO_UDP, 412 IPPROTO_UDP,
413 reply_len - sizeof (struct GNUNET_TUN_IPv6Header), 413 reply_len - off - sizeof (struct GNUNET_TUN_IPv6Header),
414 &dst->sin6_addr, 414 &dst->sin6_addr,
415 &src->sin6_addr); 415 &src->sin6_addr);
416 GNUNET_memcpy (&buf[off], &ip6, sizeof (ip6)); 416 GNUNET_memcpy (&buf[off], &ip6, sizeof (ip6));
@@ -916,7 +916,7 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
916 ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1]; 916 ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
917 if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) || 917 if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) ||
918 (ip6->version != 6) || 918 (ip6->version != 6) ||
919 (ntohs (ip6->payload_length) != msize) || 919 (ntohs (ip6->payload_length) != msize - sizeof (struct GNUNET_TUN_IPv6Header)) ||
920 (ip6->next_header != IPPROTO_UDP) ) 920 (ip6->next_header != IPPROTO_UDP) )
921 { 921 {
922 /* non-IP/UDP packet received on TUN (or with extensions) */ 922 /* non-IP/UDP packet received on TUN (or with extensions) */
@@ -924,7 +924,7 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
924 _("Received malformed IPv6-UDP packet on TUN interface.\n")); 924 _("Received malformed IPv6-UDP packet on TUN interface.\n"));
925 return GNUNET_OK; 925 return GNUNET_OK;
926 } 926 }
927 udp = (const struct GNUNET_TUN_UdpHeader*) &ip6[1]; 927 udp = (const struct GNUNET_TUN_UdpHeader *) &ip6[1];
928 msize -= sizeof (struct GNUNET_TUN_IPv6Header); 928 msize -= sizeof (struct GNUNET_TUN_IPv6Header);
929 break; 929 break;
930 default: 930 default:
@@ -939,6 +939,8 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
939 (DNS_PORT != ntohs (udp->destination_port)) ) 939 (DNS_PORT != ntohs (udp->destination_port)) )
940 { 940 {
941 /* non-DNS packet received on TUN, ignore */ 941 /* non-DNS packet received on TUN, ignore */
942 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
943 _("DNS interceptor got non-DNS packet (dropped)\n"));
942 GNUNET_STATISTICS_update (stats, 944 GNUNET_STATISTICS_update (stats,
943 gettext_noop ("# Non-DNS UDP packet received via TUN interface"), 945 gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
944 1, GNUNET_NO); 946 1, GNUNET_NO);
diff --git a/src/dns/test_gnunet_dns.sh b/src/dns/test_gnunet_dns.sh
index ab8cca4b1..84a57f87e 100755
--- a/src/dns/test_gnunet_dns.sh
+++ b/src/dns/test_gnunet_dns.sh
@@ -6,7 +6,7 @@ then
6 echo "This test only works if run as root. Skipping." 6 echo "This test only works if run as root. Skipping."
7 exit 77 7 exit 77
8fi 8fi
9if ! which sudo > /dev/null 9if ! which sudo > /dev/null
10then 10then
11 echo "This test requires sudo. Skipping." 11 echo "This test requires sudo. Skipping."
12 exit 77 12 exit 77
@@ -17,7 +17,7 @@ then
17 exit 77 17 exit 77
18fi 18fi
19if ! which nslookup > /dev/null 19if ! which nslookup > /dev/null
20then 20then
21 echo "This test requires nslookup. Skipping." 21 echo "This test requires nslookup. Skipping."
22 exit 77 22 exit 77
23fi 23fi
@@ -38,7 +38,7 @@ gnunet-dns-redirector -c dns.conf -4 127.0.0.1 &
38sleep 1 38sleep 1
39# need to run 'nslookup' as 'nobody', as gnunet-service-dns runs as root 39# need to run 'nslookup' as 'nobody', as gnunet-service-dns runs as root
40# and thus 'root' is excepted from DNS interception! 40# and thus 'root' is excepted from DNS interception!
41LO=`sudo -u nobody nslookup gnunet.org | grep Address | tail -n1` 41LO=`sudo -u nobody nslookup -type=A gnunet.org | grep Address | tail -n1`
42if [ "$LO" != "Address: 127.0.0.1" ] 42if [ "$LO" != "Address: 127.0.0.1" ]
43then 43then
44 echo "Fail: got address $LO, wanted 127.0.0.1" 44 echo "Fail: got address $LO, wanted 127.0.0.1"
diff --git a/src/include/gnunet_tun_lib.h b/src/include/gnunet_tun_lib.h
index 822a661cf..7bef0a6be 100644
--- a/src/include/gnunet_tun_lib.h
+++ b/src/include/gnunet_tun_lib.h
@@ -918,6 +918,20 @@ GNUNET_TUN_service_name_to_hash (const char *service_name,
918 918
919 919
920/** 920/**
921 * Check if two sockaddrs are equal.
922 *
923 * @param sa one address
924 * @param sb another address
925 * @param include_port also check ports
926 * @return #GNUNET_YES if they are equal
927 */
928int
929GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
930 const struct sockaddr *sb,
931 int include_port);
932
933
934/**
921 * Compute the CADET port given a service descriptor 935 * Compute the CADET port given a service descriptor
922 * (returned from #GNUNET_TUN_service_name_to_hash) and 936 * (returned from #GNUNET_TUN_service_name_to_hash) and
923 * a TCP/UDP port @a ip_port. 937 * a TCP/UDP port @a ip_port.
diff --git a/src/tun/tun.c b/src/tun/tun.c
index f39b1898b..b55de1ea9 100644
--- a/src/tun/tun.c
+++ b/src/tun/tun.c
@@ -70,7 +70,7 @@ GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
70 * 70 *
71 * @param ip header to initialize 71 * @param ip header to initialize
72 * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6 72 * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6
73 * @param payload_length number of bytes of payload that follow (excluding IPv4 header) 73 * @param payload_length number of bytes of payload that follow (excluding IPv6 header)
74 * @param src source IP address to use 74 * @param src source IP address to use
75 * @param dst destination IP address to use 75 * @param dst destination IP address to use
76 */ 76 */
@@ -268,4 +268,44 @@ GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
268} 268}
269 269
270 270
271/**
272 * Check if two sockaddrs are equal.
273 *
274 * @param sa one address
275 * @param sb another address
276 * @param include_port also check ports
277 * @return #GNUNET_YES if they are equal
278 */
279int
280GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
281 const struct sockaddr *sb,
282 int include_port)
283{
284 if (sa->sa_family != sb->sa_family)
285 return GNUNET_NO;
286
287 switch (sa->sa_family)
288 {
289 case AF_INET:
290 {
291 const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa;
292 const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb;
293 return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
294 }
295 case AF_INET6:
296 {
297 const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa;
298 const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb;
299
300 return (0 == memcmp(&sa6->sin6_addr,
301 &sb6->sin6_addr,
302 sizeof (struct in6_addr)));
303 }
304 default:
305 GNUNET_break (0);
306 return GNUNET_SYSERR;
307 }
308}
309
310
271/* end of tun.c */ 311/* end of tun.c */