aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-07 16:24:08 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-07 16:24:08 +0000
commit770f379eb23e8344b82431483613eaa72478bcdc (patch)
treebdd74b2985d8089acb5ce7c6f3e95b67a05388f4 /src/dns
parent78bdb61823b4bc4939b1fc51d66e48638d9726b2 (diff)
downloadgnunet-770f379eb23e8344b82431483613eaa72478bcdc.tar.gz
gnunet-770f379eb23e8344b82431483613eaa72478bcdc.zip
-updating DNS code to use GID match instead of source port match, introduce source port randomization
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/gnunet-helper-dns.c39
-rw-r--r--src/dns/gnunet-service-dns.c130
2 files changed, 88 insertions, 81 deletions
diff --git a/src/dns/gnunet-helper-dns.c b/src/dns/gnunet-helper-dns.c
index 5e603ceb8..2b8ce2cc9 100644
--- a/src/dns/gnunet-helper-dns.c
+++ b/src/dns/gnunet-helper-dns.c
@@ -35,7 +35,9 @@
35 * administrators must take care to not cause conflicts with these 35 * administrators must take care to not cause conflicts with these
36 * values (it was deemed safest to hardcode them as passing these 36 * values (it was deemed safest to hardcode them as passing these
37 * values as arguments might permit messing with arbitrary firewall 37 * values as arguments might permit messing with arbitrary firewall
38 * rules, which would be dangerous). 38 * rules, which would be dangerous). Traffic coming from the same
39 * group ID as the effective group ID that this process is running
40 * as is not intercepted.
39 * 41 *
40 * The code first sets up the virtual interface, then begins to 42 * The code first sets up the virtual interface, then begins to
41 * redirect the DNS traffic to it, and then on errors or SIGTERM shuts 43 * redirect the DNS traffic to it, and then on errors or SIGTERM shuts
@@ -659,7 +661,6 @@ PROCESS_BUFFER:
659 * 3: IPv6 netmask length in bits ("64") 661 * 3: IPv6 netmask length in bits ("64")
660 * 4: IPv4 address for the tunnel ("1.2.3.4") 662 * 4: IPv4 address for the tunnel ("1.2.3.4")
661 * 5: IPv4 netmask ("255.255.0.0") 663 * 5: IPv4 netmask ("255.255.0.0")
662 * 6: PORT to not hijack ("55533")
663 * @return 0 on success, otherwise code indicating type of error: 664 * @return 0 on success, otherwise code indicating type of error:
664 * 1 wrong number of arguments 665 * 1 wrong number of arguments
665 * 2 invalid arguments (i.e. port number / prefix length wrong) 666 * 2 invalid arguments (i.e. port number / prefix length wrong)
@@ -678,13 +679,12 @@ PROCESS_BUFFER:
678int 679int
679main (int argc, char *const*argv) 680main (int argc, char *const*argv)
680{ 681{
681 unsigned int port;
682 char localport[6];
683 int r; 682 int r;
684 char dev[IFNAMSIZ]; 683 char dev[IFNAMSIZ];
684 char mygid[32];
685 int fd_tun; 685 int fd_tun;
686 686
687 if (7 != argc) 687 if (6 != argc)
688 { 688 {
689 fprintf (stderr, "Fatal: must supply 6 arguments!\n"); 689 fprintf (stderr, "Fatal: must supply 6 arguments!\n");
690 return 1; 690 return 1;
@@ -714,20 +714,8 @@ main (int argc, char *const*argv)
714 return 4; 714 return 4;
715 } 715 }
716 716
717 /* validate port number */ 717 /* setup 'mygid' string */
718 port = atoi (argv[6]); 718 snprintf (mygid, sizeof (mygid), "%d", (int) getegid());
719 if ( (port == 0) || (port >= 65536) )
720 {
721 fprintf (stderr,
722 "Port `%u' is invalid\n",
723 port);
724 return 2;
725 }
726 /* print port number to string for command-line use*/
727 (void) snprintf (localport,
728 sizeof (localport),
729 "%u",
730 port);
731 719
732 /* do not die on SIGPIPE */ 720 /* do not die on SIGPIPE */
733 if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) 721 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
@@ -827,14 +815,15 @@ main (int argc, char *const*argv)
827 } 815 }
828 816
829 /* update routing tables -- next part why we need SUID! */ 817 /* update routing tables -- next part why we need SUID! */
830 /* Forward everything from the given local port (with destination 818 /* Forward everything from our EGID (which should only be held
831 to port 53, and only for UDP) without hijacking */ 819 by the 'gnunet-service-dns') and with destination
820 to port 53 on UDP, without hijacking */
832 r = 8; /* failed to fully setup routing table */ 821 r = 8; /* failed to fully setup routing table */
833 { 822 {
834 char *const mangle_args[] = 823 char *const mangle_args[] =
835 { 824 {
836 "iptables", "-t", "mangle", "-I", "OUTPUT", "1", "-p", 825 "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
837 "udp", "--sport", localport, "--dport", DNS_PORT, "-j", 826 "udp", "!", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
838 "ACCEPT", NULL 827 "ACCEPT", NULL
839 }; 828 };
840 if (0 != fork_and_exec (sbin_iptables, mangle_args)) 829 if (0 != fork_and_exec (sbin_iptables, mangle_args))
@@ -948,8 +937,8 @@ main (int argc, char *const*argv)
948 { 937 {
949 char *const mangle_clean_args[] = 938 char *const mangle_clean_args[] =
950 { 939 {
951 "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", 940 "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
952 "--sport", localport, "--dport", DNS_PORT, "-j", "ACCEPT", 941 "!", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
953 NULL 942 NULL
954 }; 943 };
955 if (0 != fork_and_exec (sbin_iptables, mangle_clean_args)) 944 if (0 != fork_and_exec (sbin_iptables, mangle_clean_args))
diff --git a/src/dns/gnunet-service-dns.c b/src/dns/gnunet-service-dns.c
index 74d3d25ac..1c772d712 100644
--- a/src/dns/gnunet-service-dns.c
+++ b/src/dns/gnunet-service-dns.c
@@ -164,7 +164,6 @@ struct RequestRecord
164}; 164};
165 165
166 166
167
168/** 167/**
169 * State we keep for each DNS tunnel that terminates at this node. 168 * State we keep for each DNS tunnel that terminates at this node.
170 */ 169 */
@@ -236,12 +235,6 @@ static GNUNET_SCHEDULER_TaskIdentifier read4_task;
236static GNUNET_SCHEDULER_TaskIdentifier read6_task; 235static GNUNET_SCHEDULER_TaskIdentifier read6_task;
237 236
238/** 237/**
239 * The port bound to the socket dnsout (and/or dnsout6). We always (try) to bind
240 * both sockets to the same port.
241 */
242static uint16_t dnsoutport;
243
244/**
245 * The configuration to use 238 * The configuration to use
246 */ 239 */
247static const struct GNUNET_CONFIGURATION_Handle *cfg; 240static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -259,7 +252,7 @@ static struct GNUNET_HELPER_Handle *hijacker;
259/** 252/**
260 * Command-line arguments we are giving to the hijacker process. 253 * Command-line arguments we are giving to the hijacker process.
261 */ 254 */
262static char *helper_argv[8]; 255static char *helper_argv[7];
263 256
264/** 257/**
265 * Head of DLL of clients we consult. 258 * Head of DLL of clients we consult.
@@ -303,6 +296,11 @@ static char *dns_exit;
303 */ 296 */
304static struct GNUNET_MESH_Handle *mesh; 297static struct GNUNET_MESH_Handle *mesh;
305 298
299/**
300 * Number of active DNS requests.
301 */
302static unsigned int dns_active;
303
306 304
307/** 305/**
308 * We're done processing a DNS request, free associated memory. 306 * We're done processing a DNS request, free associated memory.
@@ -335,7 +333,7 @@ cleanup_task (void *cls GNUNET_UNUSED,
335 333
336 GNUNET_HELPER_stop (hijacker); 334 GNUNET_HELPER_stop (hijacker);
337 hijacker = NULL; 335 hijacker = NULL;
338 for (i=0;i<8;i++) 336 for (i=0;i<7;i++)
339 GNUNET_free_non_null (helper_argv[i]); 337 GNUNET_free_non_null (helper_argv[i]);
340 if (NULL != dnsout4) 338 if (NULL != dnsout4)
341 { 339 {
@@ -561,6 +559,13 @@ send_request_to_client (struct RequestRecord *rr,
561 559
562 560
563/** 561/**
562 * Try to change the source ports we are bound to.
563 */
564static void
565change_source_ports ();
566
567
568/**
564 * A client has completed its processing for this 569 * A client has completed its processing for this
565 * request. Move on. 570 * request. Move on.
566 * 571 *
@@ -621,6 +626,7 @@ next_phase (struct RequestRecord *rr)
621 return; 626 return;
622 case RP_QUERY: 627 case RP_QUERY:
623 rr->phase = RP_INTERNET_DNS; 628 rr->phase = RP_INTERNET_DNS;
629 dns_active++;
624 switch (rr->dst_addr.ss_family) 630 switch (rr->dst_addr.ss_family)
625 { 631 {
626 case AF_INET: 632 case AF_INET:
@@ -651,6 +657,9 @@ next_phase (struct RequestRecord *rr)
651 salen); 657 salen);
652 return; 658 return;
653 case RP_INTERNET_DNS: 659 case RP_INTERNET_DNS:
660 dns_active--;
661 if (0 == dns_active)
662 change_source_ports ();
654 rr->phase = RP_MODIFY; 663 rr->phase = RP_MODIFY;
655 for (cr = clients_head; NULL != cr; cr = cr->next) 664 for (cr = clients_head; NULL != cr; cr = cr->next)
656 { 665 {
@@ -904,7 +913,6 @@ static int
904open_port4 () 913open_port4 ()
905{ 914{
906 struct sockaddr_in addr; 915 struct sockaddr_in addr;
907 socklen_t addrlen;
908 916
909 dnsout4 = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); 917 dnsout4 = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
910 if (dnsout4 == NULL) 918 if (dnsout4 == NULL)
@@ -925,25 +933,6 @@ open_port4 ()
925 dnsout4 = NULL; 933 dnsout4 = NULL;
926 return GNUNET_SYSERR; 934 return GNUNET_SYSERR;
927 } 935 }
928
929 /* Read the port we bound to */
930 addrlen = sizeof (struct sockaddr_in);
931 if (0 != getsockname (GNUNET_NETWORK_get_fd (dnsout4),
932 (struct sockaddr *) &addr,
933 &addrlen))
934 {
935 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
936 _("Could not determine port I got: %s\n"),
937 STRERROR (errno));
938 GNUNET_NETWORK_socket_close (dnsout4);
939 dnsout4 = NULL;
940 return GNUNET_SYSERR;
941 }
942 dnsoutport = htons (addr.sin_port);
943
944 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
945 _("GNUnet DNS will exit on source port %u\n"),
946 (unsigned int) dnsoutport);
947 read4_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 936 read4_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
948 dnsout4, 937 dnsout4,
949 &read_response, dnsout4); 938 &read_response, dnsout4);
@@ -961,7 +950,6 @@ static int
961open_port6 () 950open_port6 ()
962{ 951{
963 struct sockaddr_in6 addr; 952 struct sockaddr_in6 addr;
964 socklen_t addrlen;
965 953
966 dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0); 954 dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
967 if (dnsout6 == NULL) 955 if (dnsout6 == NULL)
@@ -973,7 +961,6 @@ open_port6 ()
973 } 961 }
974 memset (&addr, 0, sizeof (struct sockaddr_in6)); 962 memset (&addr, 0, sizeof (struct sockaddr_in6));
975 addr.sin6_family = AF_INET6; 963 addr.sin6_family = AF_INET6;
976 addr.sin6_port = htons (dnsoutport);
977 int err = GNUNET_NETWORK_socket_bind (dnsout6, 964 int err = GNUNET_NETWORK_socket_bind (dnsout6,
978 (struct sockaddr *) &addr, 965 (struct sockaddr *) &addr,
979 sizeof (struct sockaddr_in6)); 966 sizeof (struct sockaddr_in6));
@@ -981,29 +968,12 @@ open_port6 ()
981 if (err != GNUNET_OK) 968 if (err != GNUNET_OK)
982 { 969 {
983 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 970 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
984 _("Could not bind to port %u: %s\n"), 971 _("Could not bind: %s\n"),
985 (unsigned int) dnsoutport,
986 STRERROR (errno)); 972 STRERROR (errno));
987 GNUNET_NETWORK_socket_close (dnsout6); 973 GNUNET_NETWORK_socket_close (dnsout6);
988 dnsout6 = NULL; 974 dnsout6 = NULL;
989 return GNUNET_SYSERR; 975 return GNUNET_SYSERR;
990 } 976 }
991 if (0 == dnsoutport)
992 {
993 addrlen = sizeof (struct sockaddr_in6);
994 if (0 != getsockname (GNUNET_NETWORK_get_fd (dnsout6),
995 (struct sockaddr *) &addr,
996 &addrlen))
997 {
998 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
999 _("Could not determine port I got: %s\n"),
1000 STRERROR (errno));
1001 GNUNET_NETWORK_socket_close (dnsout6);
1002 dnsout6 = NULL;
1003 return GNUNET_SYSERR;
1004 }
1005 }
1006 dnsoutport = htons (addr.sin6_port);
1007 read6_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 977 read6_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1008 dnsout6, 978 dnsout6,
1009 &read_response, dnsout6); 979 &read_response, dnsout6);
@@ -1012,6 +982,54 @@ open_port6 ()
1012 982
1013 983
1014/** 984/**
985 * Try to change the source ports we are bound to.
986 */
987static void
988change_source_ports ()
989{
990 struct GNUNET_NETWORK_Handle *old4;
991 struct GNUNET_NETWORK_Handle *old6;
992
993 if (GNUNET_SCHEDULER_NO_TASK != read4_task)
994 {
995 GNUNET_SCHEDULER_cancel (read4_task);
996 read4_task = GNUNET_SCHEDULER_NO_TASK;
997 }
998 if (GNUNET_SCHEDULER_NO_TASK != read6_task)
999 {
1000 GNUNET_SCHEDULER_cancel (read6_task);
1001 read6_task = GNUNET_SCHEDULER_NO_TASK;
1002 }
1003 old4 = dnsout4;
1004 if (GNUNET_OK != open_port4 ())
1005 {
1006 dnsout4 = old4;
1007 read4_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1008 dnsout4,
1009 &read_response, dnsout4);
1010 }
1011 else
1012 {
1013 if (NULL != old4)
1014 GNUNET_NETWORK_socket_close (old4);
1015 }
1016 old6 = dnsout6;
1017 if (GNUNET_OK != open_port6 ())
1018 {
1019 dnsout6 = old6;
1020 read6_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1021 dnsout6,
1022 &read_response, dnsout6);
1023 }
1024 else
1025 {
1026 if (NULL != old6)
1027 GNUNET_NETWORK_socket_close (old6);
1028 }
1029}
1030
1031
1032/**
1015 * We got a new client. Make sure all new DNS requests pass by its desk. 1033 * We got a new client. Make sure all new DNS requests pass by its desk.
1016 * 1034 *
1017 * @param cls unused 1035 * @param cls unused
@@ -1216,6 +1234,12 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
1216 1234
1217 /* clean up from previous request */ 1235 /* clean up from previous request */
1218 GNUNET_free_non_null (rr->payload); 1236 GNUNET_free_non_null (rr->payload);
1237 if (RP_INTERNET_DNS == rr->phase)
1238 {
1239 dns_active--;
1240 if (0 == dns_active)
1241 change_source_ports ();
1242 }
1219 rr->payload = NULL; 1243 rr->payload = NULL;
1220 GNUNET_array_grow (rr->client_wait_list, 1244 GNUNET_array_grow (rr->client_wait_list,
1221 rr->client_wait_list_length, 1245 rr->client_wait_list_length,
@@ -1435,7 +1459,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1435 {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0}, 1459 {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
1436 {NULL, NULL, 0, 0} 1460 {NULL, NULL, 0, 0}
1437 }; 1461 };
1438 char port_s[6];
1439 char *ifc_name; 1462 char *ifc_name;
1440 char *ipv4addr; 1463 char *ipv4addr;
1441 char *ipv4mask; 1464 char *ipv4mask;
@@ -1514,12 +1537,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1514 return; 1537 return;
1515 } 1538 }
1516 helper_argv[5] = ipv4mask; 1539 helper_argv[5] = ipv4mask;
1517 GNUNET_snprintf (port_s, 1540 helper_argv[6] = NULL;
1518 sizeof (port_s),
1519 "%u",
1520 (unsigned int) dnsoutport);
1521 helper_argv[6] = GNUNET_strdup (port_s);
1522 helper_argv[7] = NULL;
1523 1541
1524 if (NULL != dns_exit) 1542 if (NULL != dns_exit)
1525 { 1543 {