]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/misc-progs/captivectrl.c
IDS: Rename sourcefire VRT rulesets to Talos VRT rulesets
[ipfire-2.x.git] / src / misc-progs / captivectrl.c
index 97d5c19d63e10aab4d450d714fe24fb44d31c8a9..56dd78db0542e48c2df7b880904485430b51a7a7 100644 (file)
@@ -71,6 +71,10 @@ static client_t* read_clients(char* filename) {
                if (line[strlen(line) - 1] == '\n')
                        line[strlen(line) - 1] = '\0';
 
+               // Skip all commented lines
+               if (*line == '#')
+                       continue;
+
                client_curr = (client_t*)malloc(sizeof(client_t));
                memset(client_curr, 0, sizeof(client_t));
 
@@ -138,29 +142,59 @@ 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];
 
        while (clients) {
-               time_t expires = clients->time_start + clients->expires;
-
-               char* time_start = format_time(&clients->time_start);
-               char* time_end   = format_time(&expires);
-
                size_t len = 0;
 
-               if (*clients->ipaddr) {
+               if (*clients->ipaddr && clients->expires > 0) {
                        len += snprintf(match + len, sizeof(match) - len,
                                "-s %s", clients->ipaddr);
                }
 
                len += snprintf(match + len, sizeof(match) - len,
-                       " -m mac --mac-source %s -m time --datestart %s --datestop %s",
-                       clients->etheraddr, time_start, time_end);
+                       " -m mac --mac-source %s", clients->etheraddr);
 
-               free(time_start);
-               free(time_end);
+               if (clients->expires > 0) {
+                       time_t expires = clients->time_start + clients->expires;
+
+                       char* time_start = format_time(&clients->time_start);
+                       char* time_end = format_time(&expires);
+
+                       len += snprintf(match + len, sizeof(match) - len,
+                               " -m time --datestart %s --datestop %s",
+                               time_start, time_end);
+
+                       free(time_start);
+                       free(time_end);
+               }
 
                // filter
                snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS"
@@ -203,14 +237,6 @@ static int add_interface_rule(const char* intf, int allow_webif_access) {
        if (r)
                return r;
 
-#if 0
-       snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL -o %s"
-               " -j CAPTIVE_PORTAL_CLIENTS", intf);
-       r = safe_system(command);
-       if (r)
-               return r;
-#endif
-
        if (allow_webif_access) {
                snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS"
                        " -i %s -p tcp --dport 444 -j RETURN", intf);
@@ -226,6 +252,13 @@ static int add_interface_rule(const char* intf, int allow_webif_access) {
        if (r)
                return r;
 
+       // Allow access to captive portal site
+       snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS"
+               " -i %s -p tcp --dport %d -j RETURN", intf, REDIRECT_PORT);
+       r = safe_system(command);
+       if (r)
+               return r;
+
        return 0;
 }
 
@@ -255,18 +288,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");
-       if (r)
-               return r;
-
-       char command[STRING_SIZE];
-       snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS"
-               " -p tcp --dport %d -j RETURN", REDIRECT_PORT);
-       r = safe_system(command);
+       r = setup_dns_filters();
        if (r)
                return r;
 
@@ -283,17 +305,20 @@ int main(int argc, char** argv) {
        char* intf = NULL;
        client_t* clients = NULL;
 
+       struct keyvalue* captive_portal_settings = NULL;
+       struct keyvalue* ethernet_settings = NULL;
+
        if (!(initsetuid()))
                exit(2);
 
-       struct keyvalue* ethernet_settings = initkeyvalues();
+       ethernet_settings = initkeyvalues();
        if (!readkeyvalues(ethernet_settings, ETHERNET_SETTINGS)) {
                fprintf(stderr, "Could not read %s\n", ETHERNET_SETTINGS);
                r = 1;
                goto END;
        }
 
-       struct keyvalue* captive_portal_settings = initkeyvalues();
+       captive_portal_settings = initkeyvalues();
        if (!readkeyvalues(captive_portal_settings, CAPTIVE_PORTAL_SETTINGS)) {
                fprintf(stderr, "Could not read %s\n", CAPTIVE_PORTAL_SETTINGS);
                r = 1;