]> git.ipfire.org Git - people/dweismueller/ipfire-2.x.git/commitdiff
captivectrl: Add protection against DNS tunnels
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 Feb 2016 16:38:34 +0000 (16:38 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 14 Dec 2016 13:02:25 +0000 (14:02 +0100)
Limit the amount of DNS traffic for each client that
has not registered, yet.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/misc-progs/captivectrl.c

index 4d0059290b38bca1d365d84dd3b9df8d8c82c11d..378ba01800fa8061d6d72eaf79c5955202b5dfdb 100644 (file)
@@ -142,6 +142,31 @@ static void flush_chains() {
        safe_system(IPTABLES " -t nat -F CAPTIVE_PORTAL");
 }
 
+static int setup_dns_filters() {
+       const char* protos[] = { "udp", "tcp", NULL };
+
+       // Limits the number of DNS requests to 3 kByte/s
+       // A burst of 1MB is permitted at the start
+       const char* limiter = "-m hashlimit --hashlimit-name dns-filter"
+               " --hashlimit-mode srcip --hashlimit-upto 3kb/sec --hashlimit-burst 1024kb";
+
+       char command[STRING_SIZE];
+
+       const char** proto = protos;
+       while (*proto) {
+               snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS -p %s"
+                       " --dport 53 %s -j RETURN", *proto, limiter);
+
+               int r = safe_system(command);
+               if (r)
+                       return r;
+
+               proto++;
+       }
+
+       return 0;
+}
+
 static int add_client_rules(const client_t* clients) {
        char command[STRING_SIZE];
        char match[STRING_SIZE];
@@ -264,11 +289,7 @@ static int add_interface_rules(struct keyvalue* captive_portal_settings, struct
        }
 
        // Always pass DNS packets through all firewall rules
-       r = safe_system(IPTABLES " -A CAPTIVE_PORTAL_CLIENTS -p udp --dport 53 -j RETURN");
-       if (r)
-               return r;
-
-       r = safe_system(IPTABLES " -A CAPTIVE_PORTAL_CLIENTS -p tcp --dport 53 -j RETURN");
+       r = setup_dns_filters();
        if (r)
                return r;