/** Remove the firewall rules * This is used when we do a clean shutdown of nodogsplash, * and when it starts, to make sure there are no rules left over from a crash */ int iptables_fw_destroy(void) { fw_quiet = 1; s_config *config; int traffic_control; LOCK_CONFIG(); config = config_get_config(); traffic_control = config->traffic_control; UNLOCK_CONFIG(); if (traffic_control) { debug(LOG_DEBUG, "Destroying our tc hooks"); tc_destroy_tc(); } debug(LOG_DEBUG, "Destroying our iptables entries"); /* Everything in the mangle table */ debug(LOG_DEBUG, "Destroying chains in the MANGLE table"); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_TRUSTED); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_BLOCKED); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_ALLOWED); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_OUTGOING); iptables_fw_destroy_mention("mangle", "POSTROUTING", CHAIN_INCOMING); iptables_do_command("-t mangle -F " CHAIN_TRUSTED); iptables_do_command("-t mangle -F " CHAIN_BLOCKED); iptables_do_command("-t mangle -F " CHAIN_ALLOWED); iptables_do_command("-t mangle -F " CHAIN_OUTGOING); iptables_do_command("-t mangle -F " CHAIN_INCOMING); iptables_do_command("-t mangle -X " CHAIN_TRUSTED); iptables_do_command("-t mangle -X " CHAIN_BLOCKED); iptables_do_command("-t mangle -X " CHAIN_ALLOWED); iptables_do_command("-t mangle -X " CHAIN_OUTGOING); iptables_do_command("-t mangle -X " CHAIN_INCOMING); /* Everything in the nat table (ip4 only) */ if (!config->ip6) { debug(LOG_DEBUG, "Destroying chains in the NAT table"); iptables_fw_destroy_mention("nat", "PREROUTING", CHAIN_OUTGOING); iptables_do_command("-t nat -F " CHAIN_OUTGOING); iptables_do_command("-t nat -X " CHAIN_OUTGOING); } /* Everything in the filter table */ debug(LOG_DEBUG, "Destroying chains in the FILTER table"); iptables_fw_destroy_mention("filter", "INPUT", CHAIN_TO_ROUTER); iptables_fw_destroy_mention("filter", "FORWARD", CHAIN_TO_INTERNET); iptables_do_command("-t filter -F " CHAIN_TO_ROUTER); iptables_do_command("-t filter -F " CHAIN_TO_INTERNET); iptables_do_command("-t filter -F " CHAIN_AUTHENTICATED); iptables_do_command("-t filter -F " CHAIN_TRUSTED); iptables_do_command("-t filter -F " CHAIN_TRUSTED_TO_ROUTER); iptables_do_command("-t filter -X " CHAIN_TO_ROUTER); iptables_do_command("-t filter -X " CHAIN_TO_INTERNET); iptables_do_command("-t filter -X " CHAIN_AUTHENTICATED); iptables_do_command("-t filter -X " CHAIN_TRUSTED); iptables_do_command("-t filter -X " CHAIN_TRUSTED_TO_ROUTER); fw_quiet = 0; return 0; }
/** Initialize the firewall rules. */ int iptables_fw_init(void) { s_config *config; int iptables_version; char *gw_interface = NULL; char *gw_ip = NULL; char *gw_address = NULL; char *gw_iprange = NULL; int gw_port = 0; char *fas_remoteip; int fas_port; int traffic_control; int set_mss, mss_value; t_MAC *pt; t_MAC *pb; t_MAC *pa; int rc = 0; int macmechanism; LOCK_CONFIG(); config = config_get_config(); gw_interface = safe_strdup(config->gw_interface); /* must free */ /* ip4 vs ip6 differences */ const char *ICMP_TYPE; if (config->ip6) { /* ip6 addresses must be in square brackets like [ffcc:e08::1] */ safe_asprintf(&gw_ip, "[%s]", config->gw_ip); /* must free */ ICMP_TYPE = "icmp6"; } else { gw_ip = safe_strdup(config->gw_ip); /* must free */ ICMP_TYPE = "icmp"; } gw_address = safe_strdup(config->gw_address); /* must free */ gw_iprange = safe_strdup(config->gw_iprange); /* must free */ gw_port = config->gw_port; fas_remoteip = safe_strdup(config->fas_remoteip); /* must free */ fas_port = config->fas_port; pt = config->trustedmaclist; pb = config->blockedmaclist; pa = config->allowedmaclist; macmechanism = config->macmechanism; set_mss = config->set_mss; mss_value = config->mss_value; traffic_control = config->traffic_control; FW_MARK_BLOCKED = config->fw_mark_blocked; FW_MARK_TRUSTED = config->fw_mark_trusted; FW_MARK_AUTHENTICATED = config->fw_mark_authenticated; UNLOCK_CONFIG(); iptables_version = get_iptables_version(); if (iptables_version < 0) { debug(LOG_ERR, "Cannot get iptables version."); return -1; } if (iptables_version < MIN_IPTABLES_VERSION) { debug(LOG_ERR, "Unsupported iptables version v%d.%d.%d, needs at least v%d.%d.%d.", (iptables_version / 10000), (iptables_version % 10000) / 100, (iptables_version % 100), (MIN_IPTABLES_VERSION / 10000), (MIN_IPTABLES_VERSION % 10000) / 100, (MIN_IPTABLES_VERSION % 100) ); return -1; } /* Set up packet marking methods */ rc |= _iptables_init_marks(); rc |= _iptables_check_mark_masking(); /* * ************************************** * Set up mangle table chains and rules * */ /* Create new chains in the mangle table */ rc |= iptables_do_command("-t mangle -N " CHAIN_TRUSTED); /* for marking trusted packets */ rc |= iptables_do_command("-t mangle -N " CHAIN_BLOCKED); /* for marking blocked packets */ rc |= iptables_do_command("-t mangle -N " CHAIN_ALLOWED); /* for marking allowed packets */ rc |= iptables_do_command("-t mangle -N " CHAIN_INCOMING); /* for counting incoming packets */ rc |= iptables_do_command("-t mangle -N " CHAIN_OUTGOING); /* for marking authenticated packets, and for counting outgoing packets */ /* Assign jumps to these new chains */ rc |= iptables_do_command("-t mangle -I PREROUTING 1 -i %s -s %s -j " CHAIN_OUTGOING, gw_interface, gw_iprange); rc |= iptables_do_command("-t mangle -I PREROUTING 2 -i %s -s %s -j " CHAIN_BLOCKED, gw_interface, gw_iprange); rc |= iptables_do_command("-t mangle -I PREROUTING 3 -i %s -s %s -j " CHAIN_TRUSTED, gw_interface, gw_iprange); rc |= iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -d %s -j " CHAIN_INCOMING, gw_interface, gw_iprange); /* Rules to mark as trusted MAC address packets in mangle PREROUTING */ for (; pt != NULL; pt = pt->next) { rc |= iptables_trust_mac(pt->mac); } /* Rules to mark as blocked MAC address packets in mangle PREROUTING */ if (MAC_BLOCK == macmechanism) { /* with the MAC_BLOCK mechanism, * MAC's on the block list are marked as blocked; * everything else passes */ for (; pb != NULL; pb = pb->next) { rc |= iptables_block_mac(pb->mac); } } else if (MAC_ALLOW == macmechanism) { /* with the MAC_ALLOW mechanism, * MAC's on the allow list pass; * everything else is to be marked as blocked */ // So, append at end of chain a rule to mark everything blocked rc |= iptables_do_command("-t mangle -A " CHAIN_BLOCKED " -j MARK %s 0x%x", markop, FW_MARK_BLOCKED); // But insert at beginning of chain rules to pass allowed MAC's for (; pa != NULL; pa = pa->next) { rc |= iptables_allow_mac(pa->mac); } } else { debug(LOG_ERR, "Unknown MAC mechanism: %d", macmechanism); rc = -1; } /* Set up for traffic control */ if (traffic_control) { rc |= tc_init_tc(); } /* * End of mangle table chains and rules ************************************** */ /* * ************************************** * Set up nat table chains and rules (ip4 only) * */ if (!config->ip6) { /* Create new chains in nat table */ rc |= iptables_do_command("-t nat -N " CHAIN_OUTGOING); /* * nat PREROUTING chain */ // packets coming in on gw_interface jump to CHAIN_OUTGOING rc |= iptables_do_command("-t nat -I PREROUTING -i %s -s %s -j " CHAIN_OUTGOING, gw_interface, gw_iprange); // CHAIN_OUTGOING, packets marked TRUSTED ACCEPT rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -m mark --mark 0x%x%s -j RETURN", FW_MARK_TRUSTED, markmask); // CHAIN_OUTGOING, packets marked AUTHENTICATED ACCEPT rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -m mark --mark 0x%x%s -j RETURN", FW_MARK_AUTHENTICATED, markmask); // CHAIN_OUTGOING, append the "preauthenticated-users" ruleset rc |= _iptables_append_ruleset("nat", "preauthenticated-users", CHAIN_OUTGOING); // Allow access to remote FAS - CHAIN_OUTGOING and CHAIN_TO_INTERNET packets for remote FAS, ACCEPT if (fas_port && strcmp(fas_remoteip, gw_ip)) { rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -p tcp --destination %s --dport %d -j ACCEPT", fas_remoteip, fas_port); } // CHAIN_OUTGOING, packets for tcp port 80, redirect to gw_port on primary address for the iface rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -p tcp --dport 80 -j DNAT --to-destination %s", gw_address); // CHAIN_OUTGOING, other packets ACCEPT rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -j ACCEPT"); } /* * End of nat table chains and rules (ip4 only) ************************************** */ /* * ************************************** * Set up filter table chains and rules * */ // Create new chains in the filter table rc |= iptables_do_command("-t filter -N " CHAIN_TO_INTERNET); rc |= iptables_do_command("-t filter -N " CHAIN_TO_ROUTER); rc |= iptables_do_command("-t filter -N " CHAIN_AUTHENTICATED); rc |= iptables_do_command("-t filter -N " CHAIN_TRUSTED); rc |= iptables_do_command("-t filter -N " CHAIN_TRUSTED_TO_ROUTER); /* * filter INPUT chain */ // packets coming in on gw_interface jump to CHAIN_TO_ROUTER rc |= iptables_do_command("-t filter -I INPUT -i %s -s %s -j " CHAIN_TO_ROUTER, gw_interface, gw_iprange); // CHAIN_TO_ROUTER packets marked BLOCKED DROP rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m mark --mark 0x%x%s -j DROP", FW_MARK_BLOCKED, markmask); // CHAIN_TO_ROUTER, invalid packets DROP rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m conntrack --ctstate INVALID -j DROP"); // CHAIN_TO_ROUTER, related and established packets ACCEPT rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); // CHAIN_TO_ROUTER, bogus SYN packets DROP rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -p tcp --tcp-flags SYN SYN \\! --tcp-option 2 -j DROP"); // CHAIN_TO_ROUTER, packets to HTTP listening on gw_port on router ACCEPT rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -p tcp --dport %d -j ACCEPT", gw_port); // CHAIN_TO_ROUTER, packets to HTTP listening on fas_port on router ACCEPT if (fas_port && !strcmp(fas_remoteip, gw_ip)) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -p tcp --dport %d -j ACCEPT", fas_port); } // CHAIN_TO_ROUTER, packets marked TRUSTED: /* if trusted-users-to-router ruleset is empty: * use empty ruleset policy * else: * jump to CHAIN_TRUSTED_TO_ROUTER, and load and use users-to-router ruleset */ if (is_empty_ruleset("trusted-users-to-router")) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m mark --mark 0x%x%s -j %s", FW_MARK_TRUSTED, markmask, get_empty_ruleset_policy("trusted-users-to-router")); } else { rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m mark --mark 0x%x%s -j " CHAIN_TRUSTED_TO_ROUTER, FW_MARK_TRUSTED, markmask); // CHAIN_TRUSTED_TO_ROUTER, related and established packets ACCEPT rc |= iptables_do_command("-t filter -A " CHAIN_TRUSTED_TO_ROUTER " -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); // CHAIN_TRUSTED_TO_ROUTER, append the "trusted-users-to-router" ruleset rc |= _iptables_append_ruleset("filter", "trusted-users-to-router", CHAIN_TRUSTED_TO_ROUTER); // CHAIN_TRUSTED_TO_ROUTER, any packets not matching that ruleset REJECT rc |= iptables_do_command("-t filter -A " CHAIN_TRUSTED_TO_ROUTER " -j REJECT --reject-with %s-port-unreachable", ICMP_TYPE); } // CHAIN_TO_ROUTER, other packets: /* if users-to-router ruleset is empty: * use empty ruleset policy * else: * load and use users-to-router ruleset */ if (is_empty_ruleset("users-to-router")) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -j %s", get_empty_ruleset_policy("users-to-router")); } else { /* CHAIN_TO_ROUTER, append the "users-to-router" ruleset */ rc |= _iptables_append_ruleset("filter", "users-to-router", CHAIN_TO_ROUTER); /* everything else, REJECT */ rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -j REJECT --reject-with %s-port-unreachable", ICMP_TYPE); } /* * filter FORWARD chain */ // packets coming in on gw_interface jump to CHAIN_TO_INTERNET rc |= iptables_do_command("-t filter -I FORWARD -i %s -s %s -j " CHAIN_TO_INTERNET, gw_interface, gw_iprange); // CHAIN_TO_INTERNET packets marked BLOCKED DROP rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j DROP", FW_MARK_BLOCKED, markmask); // CHAIN_TO_INTERNET, invalid packets DROP rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m conntrack --ctstate INVALID -j DROP"); // CHAIN_TO_INTERNET, deal with MSS if (set_mss) { /* XXX this mangles, so 'should' be done in the mangle POSTROUTING chain. * However OpenWRT standard S35firewall does it in filter FORWARD, * and since we are pre-empting that chain here, we put it in */ if (mss_value > 0) { /* set specific MSS value */ rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss %d", mss_value); } else { /* allow MSS as large as possible */ rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu"); } } // Allow access to remote FAS - CHAIN_OUTGOING and CHAIN_TO_INTERNET packets for remote FAS, ACCEPT if (fas_port && strcmp(fas_remoteip, gw_ip)) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -p tcp --destination %s --dport %d -j ACCEPT", fas_remoteip, fas_port); } /* CHAIN_TO_INTERNET, packets marked TRUSTED: */ /* if trusted-users ruleset is empty: * use empty ruleset policy * else: * jump to CHAIN_TRUSTED, and load and use trusted-users ruleset */ if (is_empty_ruleset("trusted-users")) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j %s", FW_MARK_TRUSTED, markmask, get_empty_ruleset_policy("trusted-users")); } else { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j " CHAIN_TRUSTED, FW_MARK_TRUSTED, markmask); // CHAIN_TRUSTED, related and established packets ACCEPT rc |= iptables_do_command("-t filter -A " CHAIN_TRUSTED " -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); // CHAIN_TRUSTED, append the "trusted-users" ruleset rc |= _iptables_append_ruleset("filter", "trusted-users", CHAIN_TRUSTED); // CHAIN_TRUSTED, any packets not matching that ruleset REJECT rc |= iptables_do_command("-t filter -A " CHAIN_TRUSTED " -j REJECT --reject-with %s-port-unreachable", ICMP_TYPE); } /* CHAIN_TO_INTERNET, packets marked AUTHENTICATED: */ /* if authenticated-users ruleset is empty: * use empty ruleset policy * else: * jump to CHAIN_AUTHENTICATED, and load and use authenticated-users ruleset */ if (is_empty_ruleset("authenticated-users")) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j %s", FW_MARK_AUTHENTICATED, markmask, get_empty_ruleset_policy("authenticated-users")); } else { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j " CHAIN_AUTHENTICATED, FW_MARK_AUTHENTICATED, markmask); // CHAIN_AUTHENTICATED, related and established packets ACCEPT rc |= iptables_do_command("-t filter -A " CHAIN_AUTHENTICATED " -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"); // CHAIN_AUTHENTICATED, append the "authenticated-users" ruleset rc |= _iptables_append_ruleset("filter", "authenticated-users", CHAIN_AUTHENTICATED); // CHAIN_AUTHENTICATED, any packets not matching that ruleset REJECT rc |= iptables_do_command("-t filter -A " CHAIN_AUTHENTICATED " -j REJECT --reject-with %s-port-unreachable", ICMP_TYPE); } /* CHAIN_TO_INTERNET, other packets: */ /* if preauthenticated-users ruleset is empty: * use empty ruleset policy * else: * load and use authenticated-users ruleset */ if (is_empty_ruleset("preauthenticated-users")) { rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j %s ", get_empty_ruleset_policy("preauthenticated-users")); } else { rc |= _iptables_append_ruleset("filter", "preauthenticated-users", CHAIN_TO_INTERNET); } // CHAIN_TO_INTERNET, all other packets REJECT rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j REJECT --reject-with %s-port-unreachable", ICMP_TYPE); /* * End of filter table chains and rules ************************************** */ free(gw_interface); free(gw_iprange); free(gw_ip); free(gw_address); free(fas_remoteip); return rc; }
/** * Initialize the firewall rules */ int iptables_fw_init(void) { const s_config *config; char * ext_interface = NULL; int gw_port = 0; t_trusted_mac *p; int proxy_port; fw_quiet = 0; LOCK_CONFIG(); config = config_get_config(); gw_port = config->gw_port; if (config->external_interface) { ext_interface = safe_strdup(config->external_interface); } else { ext_interface = get_ext_iface(); } if (ext_interface == NULL) { UNLOCK_CONFIG(); debug(LOG_ERR, "FATAL: no external interface"); return 0; } /* * * Everything in the MANGLE table * */ /* Create new chains */ iptables_do_command("-t mangle -N " TABLE_WIFIDOG_TRUSTED); iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING); iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING); /* Assign links and rules to these new chains */ iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface); iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_TRUSTED, config->gw_interface);//this rule will be inserted before the prior one iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " TABLE_WIFIDOG_INCOMING, config->gw_interface); for (p = config->trustedmaclist; p != NULL; p = p->next) iptables_do_command("-t mangle -A " TABLE_WIFIDOG_TRUSTED " -m mac --mac-source %s -j MARK --set-mark %d", p->mac, FW_MARK_KNOWN); /* * * Everything in the NAT table * */ /* Create new chains */ iptables_do_command("-t nat -N " TABLE_WIFIDOG_OUTGOING); iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_ROUTER); iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); iptables_do_command("-t nat -N " TABLE_WIFIDOG_GLOBAL); iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN); iptables_do_command("-t nat -N " TABLE_WIFIDOG_AUTHSERVERS); /* Assign links and rules to these new chains */ iptables_do_command("-t nat -A PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface); iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -d %s -j " TABLE_WIFIDOG_WIFI_TO_ROUTER, config->gw_address); iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_ROUTER " -j ACCEPT"); iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -j " TABLE_WIFIDOG_WIFI_TO_INTERNET); if((proxy_port=config_get_config()->proxy_port) != 0){ debug(LOG_DEBUG,"Proxy port set, setting proxy rule"); iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -p tcp --dport 80 -m mark --mark 0x%u -j REDIRECT --to-port %u", FW_MARK_KNOWN, proxy_port); iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -p tcp --dport 80 -m mark --mark 0x%u -j REDIRECT --to-port %u", FW_MARK_PROBATION, proxy_port); } iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_KNOWN); iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_PROBATION); iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_AUTHSERVERS); iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_GLOBAL); iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port); /* * * Everything in the FILTER table * */ /* Create new chains */ iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); iptables_do_command("-t filter -N " TABLE_WIFIDOG_AUTHSERVERS); iptables_do_command("-t filter -N " TABLE_WIFIDOG_LOCKED); iptables_do_command("-t filter -N " TABLE_WIFIDOG_GLOBAL); iptables_do_command("-t filter -N " TABLE_WIFIDOG_VALIDATE); iptables_do_command("-t filter -N " TABLE_WIFIDOG_KNOWN); iptables_do_command("-t filter -N " TABLE_WIFIDOG_UNKNOWN); /* Assign links and rules to these new chains */ /* Insert at the beginning */ iptables_do_command("-t filter -I FORWARD -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, config->gw_interface); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state INVALID -j DROP"); /* XXX: Why this? it means that connections setup after authentication stay open even after the connection is done... iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state RELATED,ESTABLISHED -j ACCEPT");*/ //Won't this rule NEVER match anyway?!?!? benoitg, 2007-06-23 //iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -i %s -m state --state NEW -j DROP", ext_interface); /* TCPMSS rule for PPPoE */ iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -o %s -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu", ext_interface); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_AUTHSERVERS); iptables_fw_set_authservers(); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, FW_MARK_LOCKED); iptables_load_ruleset("filter", "locked-users", TABLE_WIFIDOG_LOCKED); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_GLOBAL); iptables_load_ruleset("filter", "global", TABLE_WIFIDOG_GLOBAL); iptables_load_ruleset("nat", "global", TABLE_WIFIDOG_GLOBAL); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, FW_MARK_PROBATION); iptables_load_ruleset("filter", "validating-users", TABLE_WIFIDOG_VALIDATE); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, FW_MARK_KNOWN); iptables_load_ruleset("filter", "known-users", TABLE_WIFIDOG_KNOWN); iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); iptables_load_ruleset("filter", "unknown-users", TABLE_WIFIDOG_UNKNOWN); iptables_do_command("-t filter -A " TABLE_WIFIDOG_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable"); UNLOCK_CONFIG(); return 1; }
/* * @return A string containing human-readable status text. MUST BE free()d by caller */ char * get_status_text() { char buffer[STATUS_BUF_SIZ]; ssize_t len; s_config *config; t_auth_serv *auth_server; t_client *first; int count; unsigned long int uptime = 0; unsigned int days = 0, hours = 0, minutes = 0, seconds = 0; t_trusted_mac *p; len = 0; snprintf(buffer, (sizeof(buffer) - len), "WiFiDog status\n\n"); len = strlen(buffer); uptime = time(NULL) - started_time; days = uptime / (24 * 60 * 60); uptime -= days * (24 * 60 * 60); hours = uptime / (60 * 60); uptime -= hours * (60 * 60); minutes = uptime / 60; uptime -= minutes * 60; seconds = uptime; snprintf((buffer + len), (sizeof(buffer) - len), "Version: " VERSION "\n"); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), "Has been restarted: "); len = strlen(buffer); if (restart_orig_pid) { snprintf((buffer + len), (sizeof(buffer) - len), "yes (from PID %d)\n", restart_orig_pid); len = strlen(buffer); } else { snprintf((buffer + len), (sizeof(buffer) - len), "no\n"); len = strlen(buffer); } snprintf((buffer + len), (sizeof(buffer) - len), "Internet Connectivity: %s\n", (is_online() ? "yes" : "no")); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), "Auth server reachable: %s\n", (is_auth_online() ? "yes" : "no")); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), "Clients served this session: %lu\n\n", served_this_session); len = strlen(buffer); LOCK_CLIENT_LIST(); first = client_get_first_client(); if (first == NULL) { count = 0; } else { count = 1; while (first->next != NULL) { first = first->next; count++; } } snprintf((buffer + len), (sizeof(buffer) - len), "%d clients " "connected.\n", count); len = strlen(buffer); first = client_get_first_client(); count = 0; while (first != NULL) { snprintf((buffer + len), (sizeof(buffer) - len), "\nClient %d\n", count); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), " IP: %s MAC: %s\n", first->ip, first->mac); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), " Token: %s\n", first->token); len = strlen(buffer); snprintf((buffer + len), (sizeof(buffer) - len), " Downloaded: %llu\n Uploaded: %llu\n" , first->counters.incoming, first->counters.outgoing); len = strlen(buffer); count++; first = first->next; } UNLOCK_CLIENT_LIST(); config = config_get_config(); if (config->trustedmaclist != NULL) { snprintf((buffer + len), (sizeof(buffer) - len), "\nTrusted MAC addresses:\n"); len = strlen(buffer); for (p = config->trustedmaclist; p != NULL; p = p->next) { snprintf((buffer + len), (sizeof(buffer) - len), " %s\n", p->mac); len = strlen(buffer); } } snprintf((buffer + len), (sizeof(buffer) - len), "\nAuthentication servers:\n"); len = strlen(buffer); LOCK_CONFIG(); for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) { snprintf((buffer + len), (sizeof(buffer) - len), " Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip); len = strlen(buffer); } UNLOCK_CONFIG(); return safe_strdup(buffer); }
/* * @return A string containing human-readable status text. MUST BE free()d by caller */ char * get_status_text() { pstr_t *pstr = pstr_new(); s_config *config; t_auth_serv *auth_server; t_client *sublist, *current; int count; time_t uptime = 0; unsigned int days = 0, hours = 0, minutes = 0, seconds = 0; t_trusted_mac *p; t_offline_client *oc_list; pstr_cat(pstr, "WiFiDog status\n\n"); uptime = time(NULL) - started_time; days = (unsigned int)uptime / (24 * 60 * 60); uptime -= days * (24 * 60 * 60); hours = (unsigned int)uptime / (60 * 60); uptime -= hours * (60 * 60); minutes = (unsigned int)uptime / 60; uptime -= minutes * 60; seconds = (unsigned int)uptime; pstr_cat(pstr, "Version: " VERSION "\n"); pstr_append_sprintf(pstr, "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds); pstr_cat(pstr, "Has been restarted: "); if (restart_orig_pid) { pstr_append_sprintf(pstr, "yes (from PID %d)\n", restart_orig_pid); } else { pstr_cat(pstr, "no\n"); } pstr_append_sprintf(pstr, "Internet Connectivity: %s\n", (is_online()? "yes" : "no")); pstr_append_sprintf(pstr, "Auth server reachable: %s\n", (is_auth_online()? "yes" : "no")); pstr_append_sprintf(pstr, "Clients served this session: %lu\n\n", served_this_session); LOCK_CLIENT_LIST(); count = client_list_dup(&sublist); UNLOCK_CLIENT_LIST(); current = sublist; pstr_append_sprintf(pstr, "%d clients " "connected.\n", count); count = 1; while (current != NULL) { pstr_append_sprintf(pstr, "\nClient %d status [%d]\n", count, current->is_online); pstr_append_sprintf(pstr, " IP: %s MAC: %s\n", current->ip, current->mac); pstr_append_sprintf(pstr, " Token: %s\n", current->token); pstr_append_sprintf(pstr, " First Login: %lld\n", (long long)current->first_login); pstr_append_sprintf(pstr, " Name: %s\n", current->name != NULL?current->name:"null"); pstr_append_sprintf(pstr, " Downloaded: %llu\n Uploaded: %llu\n", current->counters.incoming, current->counters.outgoing); count++; current = current->next; } client_list_destroy(sublist); LOCK_OFFLINE_CLIENT_LIST(); pstr_append_sprintf(pstr, "%d clients " "unconnected.\n", offline_client_number()); oc_list = client_get_first_offline_client(); while(oc_list != NULL) { pstr_append_sprintf(pstr, " IP: %s MAC: %s Last Login: %lld Hit Counts: %d Client Type: %d Temp Passed: %d\n", oc_list->ip, oc_list->mac, (long long)oc_list->last_login, oc_list->hit_counts, oc_list->client_type, oc_list->temp_passed); oc_list = oc_list->next; } UNLOCK_OFFLINE_CLIENT_LIST(); config = config_get_config(); LOCK_CONFIG(); if (config->trustedmaclist != NULL) { pstr_cat(pstr, "\nTrusted MAC addresses:\n"); for (p = config->trustedmaclist; p != NULL; p = p->next) { pstr_append_sprintf(pstr, " %s\n", p->mac); } } pstr_cat(pstr, "\nAuthentication servers:\n"); for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) { pstr_append_sprintf(pstr, " Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip); } UNLOCK_CONFIG(); return pstr_to_string(pstr); }
int _connect_auth_server(int level) { s_config *config = config_get_config(); t_auth_serv *auth_server = NULL; struct in_addr *h_addr; int num_servers = 0; int retry = 0; char * hostname = NULL; char ** popularserver; char * ip; char history_ip[16]; struct sockaddr_in their_addr; int sockfd; FILE *fh; level++; for (auth_server = config->auth_servers; auth_server; auth_server = auth_server->next) { num_servers++; } debug(LOG_DEBUG, "Level %d: Calculated %d auth servers in list", level, num_servers); if (level > num_servers) { if ((fh = fopen(TMP_HISTORY_PATH, "r"))) { fscanf(fh, "%s", history_ip); fclose(fh); debug(LOG_INFO, "Connecting to history ip %s", history_ip); } if(config->auth_servers->authserv_hostname) { free(config->auth_servers->authserv_hostname); } config->auth_servers->authserv_hostname = safe_strdup(history_ip); //return (-1); } auth_server = config->auth_servers; hostname = auth_server->authserv_hostname; debug(LOG_DEBUG, "Level %d: Resolving auth server [%s]", level, hostname); h_addr = wd_gethostbyname(hostname); if (!h_addr) { for(retry = 0; retry <= 5 && !h_addr; retry++) { debug(LOG_ERR, "Level %d: try %d: Resolving auth server [%s] failes,wait 1 min try again", level, retry, hostname); sleep(60); h_addr = wd_gethostbyname(hostname); } } if (!h_addr) { /* * DNS resolving it failed * * Can we resolve any of the popular servers ? */ debug(LOG_DEBUG, "Level %d: Resolving auth server [%s] failed", level, hostname); /* * Yes * * The auth server's DNS server is probably dead. Try the next auth server */ debug(LOG_INFO, "Level %d: Marking auth server [%s] as bad and trying next if possible", level, hostname); LOCK_CONFIG(); if (auth_server->last_ip) { free(auth_server->last_ip); auth_server->last_ip = NULL; } mark_auth_server_bad(auth_server); UNLOCK_CONFIG(); return _connect_auth_server(level); } else { /* * DNS resolving was successful */ ip = safe_strdup(inet_ntoa(*h_addr)); debug(LOG_INFO, "Level %d: Resolving auth server [%s] succeeded = [%s]", level, hostname, ip); if (!auth_server->last_ip || strcmp(auth_server->last_ip, ip) != 0) { /* * But the IP address is different from the last one we knew * Update it */ debug(LOG_INFO, "Level %d: Updating last_ip IP of server [%s] to [%s]", level, hostname, ip); LOCK_CONFIG(); if (auth_server->last_ip) free(auth_server->last_ip); auth_server->last_ip = ip; UNLOCK_CONFIG(); /*backup ip to localhost*/ if ((fh = fopen(TMP_HISTORY_PATH, "w"))) { fprintf(fh, "%s", ip); fclose(fh); } /* Update firewall rules */ fw_clear_authservers(); fw_set_authservers(); } else { /* * IP is the same as last time */ free(ip); } /* if(level <= num_servers) { pthread_exit(NULL); } */ /* * Connect to it */ debug(LOG_INFO, "Level %d: Connecting to auth server %s:%d", level, hostname, auth_server->authserv_http_port); their_addr.sin_family = AF_INET; their_addr.sin_port = htons(auth_server->authserv_http_port); their_addr.sin_addr = *h_addr; memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero)); //free (h_addr); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { debug(LOG_ERR, "Level %d: Failed to create a new SOCK_STREAM socket: %s", strerror(errno)); return(-1); } if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { /* * Failed to connect * Mark the server as bad and try the next one */ debug(LOG_ERR, "Level %d: Failed to connect to auth server %s:%d (%s). Marking it as bad and trying next if possible", level, hostname, auth_server->authserv_http_port, strerror(errno)); close(sockfd); LOCK_CONFIG(); mark_auth_server_bad(auth_server); UNLOCK_CONFIG(); sleep(3); if (level > num_servers) { return (-1); } return _connect_auth_server(level); } else { /* * We have successfully connected */ debug(LOG_INFO, "Level %d: Successfully connected to auth server %s:%d", level, hostname, auth_server->authserv_http_port); return sockfd; } } }