diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-02-07 16:24:08 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-02-07 16:24:08 +0000 |
commit | 770f379eb23e8344b82431483613eaa72478bcdc (patch) | |
tree | bdd74b2985d8089acb5ce7c6f3e95b67a05388f4 /src/dns | |
parent | 78bdb61823b4bc4939b1fc51d66e48638d9726b2 (diff) | |
download | gnunet-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.c | 39 | ||||
-rw-r--r-- | src/dns/gnunet-service-dns.c | 130 |
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: | |||
678 | int | 679 | int |
679 | main (int argc, char *const*argv) | 680 | main (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; | |||
236 | static GNUNET_SCHEDULER_TaskIdentifier read6_task; | 235 | static 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 | */ | ||
242 | static uint16_t dnsoutport; | ||
243 | |||
244 | /** | ||
245 | * The configuration to use | 238 | * The configuration to use |
246 | */ | 239 | */ |
247 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 240 | static 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 | */ |
262 | static char *helper_argv[8]; | 255 | static 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 | */ |
304 | static struct GNUNET_MESH_Handle *mesh; | 297 | static struct GNUNET_MESH_Handle *mesh; |
305 | 298 | ||
299 | /** | ||
300 | * Number of active DNS requests. | ||
301 | */ | ||
302 | static 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 | */ | ||
564 | static void | ||
565 | change_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 | |||
904 | open_port4 () | 913 | open_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 | |||
961 | open_port6 () | 950 | open_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 | */ | ||
987 | static void | ||
988 | change_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 | { |