int auth_client_untrust(const char *mac) { int rc = -1; LOCK_CONFIG(); if (!remove_from_trusted_mac_list(mac) && !iptables_untrust_mac(mac)) { rc = 0; } UNLOCK_CONFIG(); /* if (rc == 0) { LOCK_CLIENT_LIST(); t_client * client = client_list_find_by_mac(mac); if (client) { rc = auth_change_state(client, FW_MARK_PREAUTHENTICATED, "manual_untrust"); if (rc == 0) { client->session_start = 0; client->session_end = 0; } } UNLOCK_CLIENT_LIST(); } */ return rc; }
int iptables_fw_deauthenticate(t_client *client) { int download_limit, upload_limit, traffic_control; s_config *config; char upload_ifbname[16]; int rc = 0; config = config_get_config(); sprintf(upload_ifbname, "ifb%d", config->upload_ifb); LOCK_CONFIG(); traffic_control = config->traffic_control; download_limit = config->download_limit; upload_limit = config->upload_limit; UNLOCK_CONFIG(); if ((client->download_limit > 0) && (client->upload_limit > 0)) { download_limit = client->download_limit; upload_limit = client->upload_limit; } /* Remove the authentication rules. */ debug(LOG_NOTICE, "Deauthenticating %s %s", client->ip, client->mac); rc |= iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x", client->ip, client->mac, markop, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j MARK %s 0x%x", client->ip, markop, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip); if (traffic_control) { rc |= tc_detach_client(config->gw_interface, download_limit, upload_ifbname, upload_limit, client->id); } return rc; }
/** Insert or delete firewall mangle rules marking a client's packets. */ int iptables_fw_authenticate(t_client *client) { int rc = 0, download_limit, upload_limit, traffic_control; s_config *config; char upload_ifbname[16]; config = config_get_config(); sprintf(upload_ifbname, "ifb%d", config->upload_ifb); LOCK_CONFIG(); traffic_control = config->traffic_control; download_limit = config->download_limit; upload_limit = config->upload_limit; UNLOCK_CONFIG(); if ((client->download_limit > 0) && (client->upload_limit > 0)) { download_limit = client->download_limit; upload_limit = client->upload_limit; } debug(LOG_NOTICE, "Authenticating %s %s", client->ip, client->mac); /* This rule is for marking upload (outgoing) packets, and for upload byte counting */ rc |= iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x", client->ip, client->mac, markop, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j MARK %s 0x%x", client->ip, markop, FW_MARK_AUTHENTICATED); /* This rule is just for download (incoming) byte counting, see iptables_fw_counters_update() */ rc |= iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip); if (traffic_control) { rc |= tc_attach_client(config->gw_interface, download_limit, upload_ifbname, upload_limit, client->id, client->ip); } return rc; }
int connect_auth_server() { int sockfd; LOCK_CONFIG(); sockfd = _connect_auth_server(0); UNLOCK_CONFIG(); return (sockfd); }
/** Insert or delete firewall mangle rules marking a client's packets. */ int iptables_fw_access(t_authaction action, t_client *client) { int rc = 0, download_limit, upload_limit, traffic_control; s_config *config; char *download_imqname, *upload_imqname; fw_quiet = 0; config = config_get_config(); safe_asprintf(&download_imqname,"imq%d",config->download_imq); /* must free */ safe_asprintf(&upload_imqname,"imq%d",config->upload_imq); /* must free */ LOCK_CONFIG(); traffic_control = config->traffic_control; download_limit = config->download_limit; upload_limit = config->upload_limit; UNLOCK_CONFIG(); if ((client->download_limit > 0) && (client->upload_limit > 0)) { download_limit = client->download_limit; upload_limit = client->upload_limit; } switch(action) { case AUTH_MAKE_AUTHENTICATED: debug(LOG_NOTICE, "Authenticating %s %s", client->ip, client->mac); /* This rule is for marking upload (outgoing) packets, and for upload byte counting */ rc |= iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x%x", client->ip, client->mac, markop, client->idx + 10, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j MARK %s 0x%x%x", client->ip, markop, client->idx + 10, FW_MARK_AUTHENTICATED); /* This rule is just for download (incoming) byte counting, see iptables_fw_counters_update() */ rc |= iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip); if (traffic_control) { rc |= tc_attach_client(download_imqname, download_limit, upload_imqname, upload_limit, client->idx, FW_MARK_AUTHENTICATED); } break; case AUTH_MAKE_DEAUTHENTICATED: /* Remove the authentication rules. */ debug(LOG_NOTICE, "Deauthenticating %s %s", client->ip, client->mac); rc |= iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x%x", client->ip, client->mac, markop, client->idx + 10, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j MARK %s 0x%x%x", client->ip, markop, client->idx + 10, FW_MARK_AUTHENTICATED); rc |= iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip); if (traffic_control) { rc |= tc_detach_client(download_imqname, upload_imqname, client->idx); } break; default: rc = -1; break; } free(upload_imqname); free(download_imqname); return rc; }
int auth_client_unblock(const char *mac) { int rc = -1; LOCK_CONFIG(); if (!remove_from_blocked_mac_list(mac) && !iptables_unblock_mac(mac)) { rc = 0; } UNLOCK_CONFIG(); return rc; }
int auth_client_block(const char *mac) { int rc = -1; LOCK_CONFIG(); if (!add_to_blocked_mac_list(mac) && !iptables_block_mac(mac)) { rc = 0; } UNLOCK_CONFIG(); return rc; }
/* Tries really hard to connect to an auth server. Returns a file descriptor, -1 on error */ int connect_auth_server() { int sockfd; LOCK_CONFIG(); sockfd = _connect_auth_server(0); UNLOCK_CONFIG(); if (sockfd == -1) { debug(LOG_ERR, "Failed to connect to any of the auth servers"); mark_auth_offline(); } else { debug(LOG_DEBUG, "Connected to auth server"); mark_auth_online(); } return (sockfd); }
static void ndsctl_untrust(int fd, char *arg) { debug(LOG_DEBUG, "Entering ndsctl_untrust..."); LOCK_CONFIG(); debug(LOG_DEBUG, "Argument: [%s]", arg); if (!remove_from_trusted_mac_list(arg) && !iptables_untrust_mac(arg)) { write(fd, "Yes", 3); } else { write(fd, "No", 2); } UNLOCK_CONFIG(); debug(LOG_DEBUG, "Exiting ndsctl_untrust."); }
static void ndsctl_allow(int fd, char *arg) { debug(LOG_DEBUG, "Entering ndsctl_allow..."); LOCK_CONFIG(); debug(LOG_DEBUG, "Argument: [%s]", arg); if (!add_to_allowed_mac_list(arg) && !iptables_allow_mac(arg)) { write(fd, "Yes", 3); } else { write(fd, "No", 2); } UNLOCK_CONFIG(); debug(LOG_DEBUG, "Exiting ndsctl_allow."); }
static char * get_maclist_text(int which) { pstr_t *pstr = NULL; s_config *config; t_trusted_mac *maclist = NULL; int line = 0; config = config_get_config(); switch(which) { case TRUSTED_MAC: pstr = pstr_new(); maclist = config->trustedmaclist; pstr_cat(pstr, "\nTrusted mac list:\n"); break; case UNTRUSTED_MAC: pstr = pstr_new(); maclist = config->mac_blacklist; pstr_cat(pstr, "\nUntrusted mac list:\n"); break; case ROAM_MAC: pstr = pstr_new(); maclist = config->roam_maclist; pstr_cat(pstr, "\nRoam mac list:\n"); break; default: return NULL; } LOCK_CONFIG(); for (; maclist != NULL; maclist = maclist->next) { pstr_append_sprintf(pstr, " %s ", maclist->mac); line++; if(line == 4) { line = 0; pstr_append_sprintf(pstr, "\n"); } } UNLOCK_CONFIG(); return pstr_to_string(pstr); }
char * get_serialize_maclist(int which) { pstr_t *pstr = NULL; s_config *config; t_trusted_mac *maclist = NULL; int line = 0; config = config_get_config(); switch(which) { case TRUSTED_MAC: maclist = config->trustedmaclist; break; case UNTRUSTED_MAC: maclist = config->mac_blacklist; break; case ROAM_MAC: maclist = config->roam_maclist; break; default: return NULL; } if(maclist != NULL) pstr = pstr_new(); else return NULL; LOCK_CONFIG(); for (; maclist != NULL; maclist = maclist->next, line++) { if(line == 0) pstr_append_sprintf(pstr, "%s", maclist->mac); else pstr_append_sprintf(pstr, ",%s", maclist->mac); } UNLOCK_CONFIG(); return pstr_to_string(pstr); }
static void ndsctl_username(int fd, char *arg) { debug(LOG_DEBUG, "Entering ndsctl_username..."); LOCK_CONFIG(); debug(LOG_DEBUG, "Argument: [%s]", arg); if (!set_username(arg)) { write(fd, "Yes", 3); debug(LOG_NOTICE, "Set username to %s.", arg); } else { write(fd, "No", 2); } UNLOCK_CONFIG(); debug(LOG_DEBUG, "Exiting ndsctl_username."); }
/* * Given a well-known name structure, generate a binary-format SID. * It's a bit perverse that we must take a text-format SID and turn it into * a binary-format SID, only to have the caller probably turn it back into * text format, but SIDs are carried across LDAP in binary format. */ static directory_error_t sid_dav(directory_values_rpc *lvals, const wksids_table_t *wksid) { char *text_sid; sid_t *sid; directory_error_t de; if (wksid->sidprefix == NULL) { RDLOCK_CONFIG(); (void) asprintf(&text_sid, "%s-%d", _idmapdstate.cfg->pgcfg.machine_sid, wksid->rid); UNLOCK_CONFIG(); } else { (void) asprintf(&text_sid, "%s-%d", wksid->sidprefix, wksid->rid); } if (text_sid == NULL) goto nomem; sid = sid_fromstr(text_sid); free(text_sid); if (sid == NULL) goto nomem; sid_to_le(sid); de = bin_list_dav(lvals, sid, 1, sid_len(sid)); sid_free(sid); return (de); nomem: return (directory_error("ENOMEM.sid_dav", "No memory allocating SID for user lookup", NULL)); }
static void ndsctl_loglevel(int fd, char *arg) { int level = atoi(arg); debug(LOG_DEBUG, "Entering ndsctl_loglevel..."); LOCK_CONFIG(); debug(LOG_DEBUG, "Argument: [%s]", arg); if (!set_log_level(level)) { write(fd, "Yes", 3); debug(LOG_NOTICE, "Set debug loglevel to %d.", level); } else { write(fd, "No", 2); } UNLOCK_CONFIG(); debug(LOG_DEBUG, "Exiting ndsctl_loglevel."); }
/** in connect function emong added,for quickly find useable server */ int in_connect_auth_server(t_auth_serv *server) { int sockfd,level=0; s_config *config = config_get_config(); t_auth_serv *tmp_server; for (tmp_server = config->auth_servers; tmp_server; tmp_server = tmp_server->next) { if(tmp_server == server) //find it break; ++level; } LOCK_CONFIG(); sockfd = _connect_auth_server(level,0); UNLOCK_CONFIG(); if (sockfd == -1) { debug(LOG_ERR, "Failed to connect to any of the auth servers"); mark_auth_offline(); } else { debug(LOG_DEBUG, "Connected to auth server"); mark_auth_online(); } return (sockfd); }
/* * @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); }
void print_idmapdstate(void) { int i, j; idmap_pg_config_t *pgcfg; idmap_trustedforest_t *tf; RDLOCK_CONFIG(); if (_idmapdstate.cfg == NULL) { idmapdlog(LOG_INFO, "Null configuration"); UNLOCK_CONFIG(); return; } pgcfg = &_idmapdstate.cfg->pgcfg; idmapdlog(LOG_DEBUG, "list_size_limit=%llu", pgcfg->list_size_limit); idmapdlog(LOG_DEBUG, "default_domain=%s", CHECK_NULL(pgcfg->default_domain)); idmapdlog(LOG_DEBUG, "domain_name=%s", CHECK_NULL(pgcfg->domain_name)); idmapdlog(LOG_DEBUG, "machine_sid=%s", CHECK_NULL(pgcfg->machine_sid)); if (pgcfg->domain_controller == NULL || pgcfg->domain_controller[0].host[0] == '\0') { idmapdlog(LOG_DEBUG, "No domain controllers known"); } else { for (i = 0; pgcfg->domain_controller[i].host[0] != '\0'; i++) idmapdlog(LOG_DEBUG, "domain_controller=%s port=%d", pgcfg->domain_controller[i].host, pgcfg->domain_controller[i].port); } idmapdlog(LOG_DEBUG, "forest_name=%s", CHECK_NULL(pgcfg->forest_name)); idmapdlog(LOG_DEBUG, "site_name=%s", CHECK_NULL(pgcfg->site_name)); if (pgcfg->global_catalog == NULL || pgcfg->global_catalog[0].host[0] == '\0') { idmapdlog(LOG_DEBUG, "No global catalog servers known"); } else { for (i = 0; pgcfg->global_catalog[i].host[0] != '\0'; i++) idmapdlog(LOG_DEBUG, "global_catalog=%s port=%d", pgcfg->global_catalog[i].host, pgcfg->global_catalog[i].port); } if (pgcfg->domains_in_forest == NULL || pgcfg->domains_in_forest[0].domain[0] == '\0') { idmapdlog(LOG_DEBUG, "No domains in forest %s known", CHECK_NULL(pgcfg->forest_name)); } else { for (i = 0; pgcfg->domains_in_forest[i].domain[0] != '\0'; i++) idmapdlog(LOG_DEBUG, "domains in forest %s = %s", CHECK_NULL(pgcfg->forest_name), pgcfg->domains_in_forest[i].domain); } if (pgcfg->trusted_domains == NULL || pgcfg->trusted_domains[0].domain[0] == '\0') { idmapdlog(LOG_DEBUG, "No trusted domains known"); } else { for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) idmapdlog(LOG_DEBUG, "trusted domain = %s", pgcfg->trusted_domains[i].domain); } for (i = 0; i < pgcfg->num_trusted_forests; i++) { tf = &pgcfg->trusted_forests[i]; for (j = 0; tf->global_catalog[j].host[0] != '\0'; j++) idmapdlog(LOG_DEBUG, "trusted forest %s global_catalog=%s port=%d", tf->forest_name, tf->global_catalog[j].host, tf->global_catalog[j].port); for (j = 0; tf->domains_in_forest[j].domain[0] != '\0'; j++) { if (tf->domains_in_forest[j].trusted) { idmapdlog(LOG_DEBUG, "trusted forest %s domain=%s", tf->forest_name, tf->domains_in_forest[j].domain); } } } idmapdlog(LOG_DEBUG, "directory_based_mapping=%s", enum_lookup(pgcfg->directory_based_mapping, directory_mapping_map)); idmapdlog(LOG_DEBUG, "ad_unixuser_attr=%s", CHECK_NULL(pgcfg->ad_unixuser_attr)); idmapdlog(LOG_DEBUG, "ad_unixgroup_attr=%s", CHECK_NULL(pgcfg->ad_unixgroup_attr)); idmapdlog(LOG_DEBUG, "nldap_winname_attr=%s", CHECK_NULL(pgcfg->nldap_winname_attr)); UNLOCK_CONFIG(); }
/* * Given a well-known name entry and a list of attributes that were * requested, populate the structure to return to the caller. */ static directory_error_t directory_provider_builtin_populate( directory_entry_rpc *pent, const wksids_table_t *wksid, idmap_utf8str_list *attrs) { int j; directory_values_rpc *llvals; int nattrs; nattrs = attrs->idmap_utf8str_list_len; llvals = calloc(nattrs, sizeof (directory_values_rpc)); if (llvals == NULL) goto nomem; pent->status = DIRECTORY_FOUND; pent->directory_entry_rpc_u.attrs.attrs_val = llvals; pent->directory_entry_rpc_u.attrs.attrs_len = nattrs; for (j = 0; j < nattrs; j++) { directory_values_rpc *val; char *a; directory_error_t de; /* * We're going to refer to these a lot, so make a shorthand * copy. */ a = attrs->idmap_utf8str_list_val[j]; val = &llvals[j]; /* * Start by assuming no errors and that we don't have * the information. */ val->found = FALSE; de = NULL; if (uu_strcaseeq(a, "uid")) { de = str_list_dav(val, &wksid->winname, 1); } else if (uu_strcaseeq(a, "uidNumber")) { if (wksid->pid != IDMAP_SENTINEL_PID && wksid->is_user) { de = uint_list_dav(val, &wksid->pid, 1); } } else if (uu_strcaseeq(a, "gidNumber")) { if (wksid->pid != IDMAP_SENTINEL_PID && !wksid->is_user) { de = uint_list_dav(val, &wksid->pid, 1); } } else if (uu_strcaseeq(a, "displayName") || uu_strcaseeq(a, "cn")) { de = str_list_dav(val, &wksid->winname, 1); } else if (uu_strcaseeq(a, "distinguishedName")) { char *container; if (wksid->domain == NULL) { container = "Users"; } else { container = "Builtin"; } RDLOCK_CONFIG(); char *dn; (void) asprintf(&dn, "CN=%s,CN=%s,DC=%s", wksid->winname, container, _idmapdstate.hostname); UNLOCK_CONFIG(); const char *cdn = dn; de = str_list_dav(val, &cdn, 1); free(dn); } else if (uu_strcaseeq(a, "objectClass")) { if (wksid->is_wuser) { static const char *objectClasses[] = { "top", "person", "organizationalPerson", "user", }; de = str_list_dav(val, objectClasses, UU_NELEM(objectClasses)); } else { static const char *objectClasses[] = { "top", "group", }; de = str_list_dav(val, objectClasses, UU_NELEM(objectClasses)); } } else if (uu_strcaseeq(a, "objectSid")) { de = sid_dav(val, wksid); } else if (uu_strcaseeq(a, "x-sun-canonicalName")) { char *canon; if (wksid->domain == NULL) { RDLOCK_CONFIG(); (void) asprintf(&canon, "%s@%s", wksid->winname, _idmapdstate.hostname); UNLOCK_CONFIG(); } else if (uu_streq(wksid->domain, "")) { canon = strdup(wksid->winname); } else { (void) asprintf(&canon, "%s@%s", wksid->winname, wksid->domain); } if (canon == NULL) goto nomem; const char *ccanon = canon; de = str_list_dav(val, &ccanon, 1); free(canon); } else if (uu_strcaseeq(a, "x-sun-provider")) { const char *provider = "Builtin"; de = str_list_dav(val, &provider, 1); } if (de != NULL) return (de); } return (NULL); nomem: return (directory_error("ENOMEM.users", "No memory allocating return value for user lookup", NULL)); }
/* * @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); }
/** Initialize the firewall rules. */ int iptables_fw_init(void) { s_config *config; char * gw_interface = NULL; char * gw_address = NULL; char * gw_iprange = NULL; int gw_port = 0; int traffic_control; int set_mss, mss_value; t_MAC *pt; t_MAC *pb; t_MAC *pa; int rc = 0, mmask = 0, macmechanism; LOCK_CONFIG(); config = config_get_config(); gw_interface = safe_strdup(config->gw_interface); /* must free */ gw_address = safe_strdup(config->gw_address); /* must free */ gw_iprange = safe_strdup(config->gw_iprange); /* must free */ gw_port = config->gw_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(); /* 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_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 * */ /* 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 -A 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 ACCEPT", 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 ACCEPT",FW_MARK_AUTHENTICATED, markmask); /* CHAIN_OUTGOING, append the "preauthenticated-users" ruleset */ rc |= _iptables_append_ruleset("nat", "preauthenticated-users", CHAIN_OUTGOING); /* 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:%d", gw_address, gw_port); /* CHAIN_OUTGOING, other packets ACCEPT */ rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -j ACCEPT"); /* * End of nat table chains and rules ************************************** */ /* * ************************************** * 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 state --state INVALID -j DROP"); /* CHAIN_TO_ROUTER, related and established packets ACCEPT */ rc |= iptables_do_command("-t filter -A " CHAIN_TO_ROUTER " -m state --state 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 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 state --state 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 icmp-port-unreachable"); } /* 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 icmp-port-unreachable"); } /* * filter FORWARD chain */ /* packets coming in on gw_interface jump to CHAIN_TO_INTERNET */ rc |= iptables_do_command("-t filter -A 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 state --state 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"); } } /* 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 state --state 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 icmp-port-unreachable"); } /* 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 state --state 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 icmp-port-unreachable"); } /* 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 icmp-port-unreachable"); /* * End of filter table chains and rules ************************************** */ free(gw_interface); free(gw_iprange); free(gw_address); return rc; }
int iptables_fw_init(void) { const s_config *config; char * ext_interface = NULL; // 获取WAN口名称 int gw_port = 0; t_trusted_mac *p; 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(); // 获取WAN口名称 } if (ext_interface == NULL) { UNLOCK_CONFIG(); debug(LOG_ERR, "FATAL: no external interface"); return 0; } /* * * Everything in the MANGLE table * */ /* Create new chains */// 创建自定义规则链 // modified by lijg, 2013-05-17, 取消打标记 //iptables_do_command("-t mangle -N " TABLE_WIFIDOG_TRUSTED); IPT_DO_CMMD("-t mangle -N " TABLE_WIFIDOG_OUTGOING); IPT_DO_CMMD("-t mangle -N " TABLE_WIFIDOG_INCOMING); /* Assign links and rules to these new chains */ // modified by lijg, 2013-04-24, avoid confliting with QoS IPT_DO_CMMD("-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 IPT_DO_CMMD("-t mangle -I POSTROUTING 1 -o %s -j " TABLE_WIFIDOG_INCOMING, config->gw_interface); // modified by lijg, 2013-05-17, avoid confliting with QoS //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 --or-mark %d", p->mac, FW_MARK_KNOWN); /* * * Everything in the NAT table * */ /* Create new chains */ IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_OUTGOING); IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_WIFI_TO_ROUTER); IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_GLOBAL); IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_UNKNOWN); IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_AUTHSERVERS); // add by lijg, 2013-08-14, create chains for white list IPT_DO_CMMD("-t nat -N " TABLE_WIFIDOG_WLIST); /* Assign links and rules to these new chains */ IPT_DO_CMMD("-t nat -A PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_OUTGOING " -d %s -j " TABLE_WIFIDOG_WIFI_TO_ROUTER, config->gw_address); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_WIFI_TO_ROUTER " -j ACCEPT"); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_OUTGOING " -j " TABLE_WIFIDOG_WIFI_TO_INTERNET); // modified by lijg, 2013-04-24, match mark mask = ff00 IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%04x/0xff00 -j ACCEPT", FW_MARK_KNOWN); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%04x/0xff00 -j ACCEPT", FW_MARK_PROBATION); // add by lijg, 2013-08-14, add a white list chain IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_WLIST); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); IPT_DO_CMMD("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_AUTHSERVERS); // modified by lijg, 2013-05-17, 取消该规则 //iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_GLOBAL); IPT_DO_CMMD("-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 */ IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_AUTHSERVERS); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_LOCKED); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_GLOBAL); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_VALIDATE); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_KNOWN); IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_UNKNOWN); // add by lijg, 2013-08-14, create chains for white list IPT_DO_CMMD("-t filter -N " TABLE_WIFIDOG_WLIST); /* Assign links and rules to these new chains */ /* Insert at the beginning */ IPT_DO_CMMD("-t filter -I FORWARD -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, config->gw_interface); //IPT_DO_CMMD("-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 */ // modified by lijg, 2013-05-28, cancel this fw rule , repeated in openwrt FW rules //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); IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_AUTHSERVERS); iptables_fw_set_authservers(); // modified by lijg, 2013-05-17, 取消匹配标记 //iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%04x/0xff00 -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); // modified by lijg, 2013-05-17, 取消该规则 IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%04x/0xff00 -j " TABLE_WIFIDOG_VALIDATE, FW_MARK_PROBATION); iptables_load_ruleset("filter", "validating-users", TABLE_WIFIDOG_VALIDATE); // add by lijg, 2013-08-14, add a white list chain IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_WLIST); // modified by lijg, 2013-05-17, 取消打标记 IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%04x/0xff00 -j " TABLE_WIFIDOG_KNOWN, FW_MARK_KNOWN); iptables_load_ruleset("filter", "known-users", TABLE_WIFIDOG_KNOWN); IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); iptables_load_ruleset("filter", "unknown-users", TABLE_WIFIDOG_UNKNOWN); IPT_DO_CMMD("-t filter -A " TABLE_WIFIDOG_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable"); // add by lijg, 2013-08-14, Load wwlist config rule load_wwlist_conf("/etc/config/wwlist"); UNLOCK_CONFIG(); // add by lijg, 2013-05-17, free(ext_interface); return 1; }
/** 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 " CHAIN_TRUSTED); iptables_do_command("-t mangle -N " CHAIN_OUTGOING); iptables_do_command("-t mangle -N " CHAIN_INCOMING); /* Assign links and rules to these new chains */ iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_OUTGOING, config->gw_interface); iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_TRUSTED, config->gw_interface); //this rule will be inserted before the prior one iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " CHAIN_INCOMING, config->gw_interface); for (p = config->trustedmaclist; p != NULL; p = p->next) iptables_do_command("-t mangle -A " CHAIN_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 " CHAIN_OUTGOING); iptables_do_command("-t nat -N " CHAIN_TO_ROUTER); iptables_do_command("-t nat -N " CHAIN_TO_INTERNET); iptables_do_command("-t nat -N " CHAIN_GLOBAL); iptables_do_command("-t nat -N " CHAIN_UNKNOWN); iptables_do_command("-t nat -N " CHAIN_AUTHSERVERS); /* Assign links and rules to these new chains */ iptables_do_command("-t nat -A PREROUTING -i %s -j " CHAIN_OUTGOING, config->gw_interface); iptables_do_command("-t nat -A " CHAIN_OUTGOING " -d %s -j " CHAIN_TO_ROUTER, config->gw_address); iptables_do_command("-t nat -A " CHAIN_TO_ROUTER " -j ACCEPT"); iptables_do_command("-t nat -A " CHAIN_OUTGOING " -j " CHAIN_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 " CHAIN_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 " CHAIN_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 " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_KNOWN); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_PROBATION); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -j " CHAIN_UNKNOWN); iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTHSERVERS); iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_GLOBAL); iptables_do_command("-t nat -A " CHAIN_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 " CHAIN_TO_INTERNET); iptables_do_command("-t filter -N " CHAIN_AUTHSERVERS); iptables_do_command("-t filter -N " CHAIN_LOCKED); iptables_do_command("-t filter -N " CHAIN_GLOBAL); iptables_do_command("-t filter -N " CHAIN_VALIDATE); iptables_do_command("-t filter -N " CHAIN_KNOWN); iptables_do_command("-t filter -N " CHAIN_UNKNOWN); /* Assign links and rules to these new chains */ /* Insert at the beginning */ iptables_do_command("-t filter -I FORWARD -i %s -j " CHAIN_TO_INTERNET, config->gw_interface); iptables_do_command("-t filter -A " CHAIN_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 " CHAIN_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 " CHAIN_TO_INTERNET " -i %s -m state --state NEW -j DROP", ext_interface); /* TCPMSS rule for PPPoE */ iptables_do_command("-t filter -A " CHAIN_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 " CHAIN_TO_INTERNET " -j " CHAIN_AUTHSERVERS); iptables_fw_set_authservers(); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j " CHAIN_LOCKED, FW_MARK_LOCKED); iptables_load_ruleset("filter", FWRULESET_LOCKED_USERS, CHAIN_LOCKED); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_GLOBAL); iptables_load_ruleset("filter", FWRULESET_GLOBAL, CHAIN_GLOBAL); iptables_load_ruleset("nat", FWRULESET_GLOBAL, CHAIN_GLOBAL); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j " CHAIN_VALIDATE, FW_MARK_PROBATION); iptables_load_ruleset("filter", FWRULESET_VALIDATING_USERS, CHAIN_VALIDATE); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j " CHAIN_KNOWN, FW_MARK_KNOWN); iptables_load_ruleset("filter", FWRULESET_KNOWN_USERS, CHAIN_KNOWN); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_UNKNOWN); iptables_load_ruleset("filter", FWRULESET_UNKNOWN_USERS, CHAIN_UNKNOWN); iptables_do_command("-t filter -A " CHAIN_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable"); UNLOCK_CONFIG(); free(ext_interface); return 1; }
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; } } }