diff --git a/src/conf.c b/src/conf.c index e5012961..87a2fb78 100644 --- a/src/conf.c +++ b/src/conf.c @@ -102,6 +102,7 @@ typedef enum { oSSLPeerVerification, oSSLCertPath, oSSLAllowedCipherList, + oMarkOffsetBits, } OpCodes; /** @internal @@ -147,6 +148,7 @@ static const struct { "sslpeerverification", oSSLPeerVerification}, { "sslcertpath", oSSLCertPath}, { "sslallowedcipherlist", oSSLAllowedCipherList}, { + "markoffsetbits", oMarkOffsetBits}, { NULL, oBadOption},}; static void config_notnull(const void *, const char *); @@ -201,6 +203,7 @@ config_init(void) config.ssl_verify = DEFAULT_AUTHSERVSSLPEERVER; config.ssl_cipher_list = NULL; config.arp_table_path = safe_strdup(DEFAULT_ARPTABLE); + config.markoffsetbits = DEFAULT_MARKOFFSETBITS; debugconf.log_stderr = 1; debugconf.debuglevel = DEFAULT_DEBUGLEVEL; @@ -785,6 +788,14 @@ config_read(const char *filename) debug(LOG_WARNING, "SSLAllowedCipherList is set but no SSL compiled in. Ignoring!"); #endif break; + case oMarkOffsetBits: + sscanf(p1, "%u", &config.markoffsetbits); + if (config.markoffsetbits > 31) { + config.markoffsetbits = 0; + debug(LOG_WARNING, "MarkOffsetBits is invalid. It should be in the range of 0 to 31. " + "Fallback to no offset!"); + } + break; case oBadOption: /* FALL THROUGH */ default: diff --git a/src/conf.h b/src/conf.h index 6200cd68..6316ba6c 100644 --- a/src/conf.h +++ b/src/conf.h @@ -67,6 +67,7 @@ #define DEFAULT_AUTHSERVSSLPEERVER 1 /* 0 means: Enable peer verification */ #define DEFAULT_ARPTABLE "/proc/net/arp" /*@}*/ +#define DEFAULT_MARKOFFSETBITS 0 /*@{*/ /** Defines for firewall rule sets. */ @@ -192,6 +193,8 @@ typedef struct { char *arp_table_path; /**< @brief Path to custom ARP table, formatted like /proc/net/arp */ t_popular_server *popular_servers; /**< @brief list of popular servers */ + unsigned int markoffsetbits; /**< @brief bits, left shifted mark values + for n bits */ } s_config; /** @brief Get the current gateway configuration */ diff --git a/src/fw_iptables.c b/src/fw_iptables.c index f526aa8a..943a7a15 100644 --- a/src/fw_iptables.c +++ b/src/fw_iptables.c @@ -287,8 +287,8 @@ iptables_fw_init(void) 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); + iptables_do_command("-t mangle -A " CHAIN_TRUSTED " -m mac --mac-source %s -j MARK --set-mark 0x%x", p->mac, + FW_MARK_KNOWN << config->markoffsetbits); /* * @@ -317,22 +317,32 @@ iptables_fw_init(void) 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, + " -p tcp --dport 80 -m mark --mark 0x%x/0x%x -j REDIRECT --to-port %u", + FW_MARK_KNOWN << config->markoffsetbits, + FW_MARK_KNOWN << config->markoffsetbits, 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, + " -p tcp --dport 80 -m mark --mark 0x%x/0x%x -j REDIRECT --to-port %u", + FW_MARK_PROBATION << config->markoffsetbits, + FW_MARK_PROBATION << config->markoffsetbits, 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 " -m mark --mark 0x%x/0x%x -j ACCEPT", + FW_MARK_KNOWN << config->markoffsetbits, + FW_MARK_KNOWN << config->markoffsetbits); + iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x/0x%x -j ACCEPT", + FW_MARK_PROBATION << config->markoffsetbits, + FW_MARK_PROBATION << config->markoffsetbits); 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); if (got_authdown_ruleset) { iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTH_IS_DOWN); - iptables_do_command("-t nat -A " CHAIN_AUTH_IS_DOWN " -m mark --mark 0x%u -j ACCEPT", FW_MARK_AUTH_IS_DOWN); + iptables_do_command("-t nat -A " CHAIN_AUTH_IS_DOWN " -m mark --mark 0x%x/0x%x -j ACCEPT", + FW_MARK_AUTH_IS_DOWN << config->markoffsetbits, + FW_MARK_AUTH_IS_DOWN << config->markoffsetbits); } iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port); @@ -374,22 +384,29 @@ iptables_fw_init(void) 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_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x/0x%x -j " CHAIN_LOCKED, + FW_MARK_LOCKED << config->markoffsetbits, + FW_MARK_LOCKED << config->markoffsetbits); 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_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x/0x%x -j " CHAIN_VALIDATE, + FW_MARK_PROBATION << config->markoffsetbits, + FW_MARK_PROBATION << config->markoffsetbits); 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_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x/0x%x -j " CHAIN_KNOWN, + FW_MARK_KNOWN << config->markoffsetbits, + FW_MARK_KNOWN << config->markoffsetbits); iptables_load_ruleset("filter", FWRULESET_KNOWN_USERS, CHAIN_KNOWN); if (got_authdown_ruleset) { - iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j " CHAIN_AUTH_IS_DOWN, - FW_MARK_AUTH_IS_DOWN); + iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x/0x%x -j " CHAIN_AUTH_IS_DOWN, + FW_MARK_AUTH_IS_DOWN << config->markoffsetbits, + FW_MARK_AUTH_IS_DOWN << config->markoffsetbits); iptables_load_ruleset("filter", FWRULESET_AUTH_IS_DOWN, CHAIN_AUTH_IS_DOWN); } @@ -554,20 +571,21 @@ iptables_fw_destroy_mention(const char *table, const char *chain, const char *me int iptables_fw_access(fw_access_t type, const char *ip, const char *mac, int tag) { + const s_config *config = config_get_config (); int rc; fw_quiet = 0; switch (type) { case FW_ACCESS_ALLOW: - iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, - mac, tag); + iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark 0x%x", ip, + mac, tag << config->markoffsetbits); rc = iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", ip); break; case FW_ACCESS_DENY: /* XXX Add looping to really clear? */ - iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, - mac, tag); + iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark 0x%x", ip, + mac, tag << config->markoffsetbits); rc = iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j ACCEPT", ip); break; default: @@ -606,9 +624,11 @@ iptables_fw_access_host(fw_access_t type, const char *host) int iptables_fw_auth_unreachable(int tag) { + const s_config *config = config_get_config (); int got_authdown_ruleset = NULL == get_ruleset(FWRULESET_AUTH_IS_DOWN) ? 0 : 1; if (got_authdown_ruleset) - return iptables_do_command("-t mangle -A " CHAIN_AUTH_IS_DOWN " -j MARK --set-mark 0x%u", tag); + return iptables_do_command("-t mangle -A " CHAIN_AUTH_IS_DOWN " -j MARK --set-mark 0x%x", + tag << config->markoffsetbits); else return 1; }