diff --git a/server/fw_util.c b/server/fw_util.c index 51f06632..a2950b76 100644 --- a/server/fw_util.c +++ b/server/fw_util.c @@ -137,7 +137,7 @@ delete_all_chains(void) char cmd_buf[CMD_BUFSIZE] = {0}; char err[CMD_BUFSIZE] = {0}; - for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES-1); i++) + for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++) { if(fwc.chain[i].target[0] == '\0') continue; @@ -193,7 +193,7 @@ create_fw_chains(void) char cmd_buf[CMD_BUFSIZE] = {0}; char err[CMD_BUFSIZE] = {0}; - for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES-1); i++) + for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++) { if(fwc.chain[i].target[0] == '\0') continue; @@ -206,7 +206,7 @@ create_fw_chains(void) fwc.chain[i].to_chain ); - //printf("CMD: '%s'\n", cmd_buf); + //printf("(%i) CMD: '%s'\n", i, cmd_buf); res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); /* Expect full success on this */ if(! EXTCMD_IS_SUCCESS(res)) @@ -227,7 +227,7 @@ create_fw_chains(void) fwc.chain[i].to_chain ); - //printf("CMD: '%s'\n", cmd_buf); + //printf("(%i) CMD: '%s'\n", i, cmd_buf); res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); /* Expect full success on this */ if(! EXTCMD_IS_SUCCESS(res)) @@ -371,8 +371,8 @@ fw_initialize(fko_srv_options_t *opts) * this. * */ - if(opts->config[CONF_ENABLE_IPT_SNAT] != NULL - && strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "_CHANGE_ME_", 11)!=0) + if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL + && strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "_CHANGEME_", 10)!=0) { if(opts->config[CONF_IPT_SNAT_ACCESS] != NULL) set_fw_chain_conf(IPT_SNAT_ACCESS, opts->config[CONF_IPT_SNAT_ACCESS]); @@ -415,11 +415,12 @@ fw_cleanup(void) /* Rule Processing - Create an access request... */ int -process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) +process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat) { char cmd_buf[CMD_BUFSIZE] = {0}; char err[CMD_BUFSIZE] = {0}; char nat_ip[16] = {0}; + char snat_target[SNAT_TARGET_BUFSIZE] = {0}; char *ndx; unsigned int nat_port = 0;; @@ -427,14 +428,14 @@ process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) acc_port_list_t *port_list = NULL; acc_port_list_t *ple; - unsigned int cproto; - unsigned int cport; + unsigned int fst_proto; + unsigned int fst_port; - struct fw_chain *in_chain = &(opts->fw_config->chain[IPT_INPUT_ACCESS]); - struct fw_chain *out_chain = &(opts->fw_config->chain[IPT_OUTPUT_ACCESS]); - struct fw_chain *fwd_chain = &(opts->fw_config->chain[IPT_FORWARD_ACCESS]); + struct fw_chain *in_chain = &(opts->fw_config->chain[IPT_INPUT_ACCESS]); + struct fw_chain *out_chain = &(opts->fw_config->chain[IPT_OUTPUT_ACCESS]); + struct fw_chain *fwd_chain = &(opts->fw_config->chain[IPT_FORWARD_ACCESS]); struct fw_chain *dnat_chain = &(opts->fw_config->chain[IPT_DNAT_ACCESS]); - struct fw_chain *snat_chain; // We assign this later (when we get it done) + struct fw_chain *snat_chain; /* We assign this later (if we need to). */ int status, res; time_t now, exp_ts; @@ -443,103 +444,116 @@ process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) */ expand_acc_port_list(&port_list, spadat->spa_message_remain); - /* Create an access command for each proto/port for the source ip. + /* Start at the top of the proto-port list... */ ple = port_list; - cproto = ple->proto; - cport = ple->port; + /* Remember the first proto/port combo in case we need them + * for NAT access requests. + */ + fst_proto = ple->proto; + fst_port = ple->port; - while(ple != NULL) + /* Set our expire time value. + */ + time(&now); + exp_ts = now + spadat->fw_access_timeout; + + /* For straight access requests, we currently support multiple proto/port + * request. + */ + if(spadat->message_type == FKO_ACCESS_MSG + || spadat->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG) { - time(&now); - exp_ts = now + spadat->fw_access_timeout; - - memset(cmd_buf, 0x0, CMD_BUFSIZE); - - snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_RULE_ARGS, - opts->fw_config->fw_command, - in_chain->table, - in_chain->to_chain, - ple->proto, - spadat->use_src_ip, - ple->port, - exp_ts, - in_chain->target - ); - -//--DSS tmp -//fprintf(stderr, "ADD CMD: %s\n", cmd_buf); - res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); - if(EXTCMD_IS_SUCCESS(res)) - { - log_msg(LOG_INFO, "Added Rule to %s for %s, %s expires at %u", - in_chain->to_chain, spadat->use_src_ip, - spadat->spa_message_remain, exp_ts - ); - - in_chain->active_rules++; - - /* Reset the next expected expire time for this chain if it - * is warranted. - */ - if(in_chain->next_expire < now || exp_ts < in_chain->next_expire) - in_chain->next_expire = exp_ts; - } - else - parse_extcmd_error(res, status, err); - - /* If we have to make an corresponding OUTPUT rule if out_chain target - * is not NULL. + /* Create an access command for each proto/port for the source ip. */ - if(out_chain->to_chain != NULL && strlen(out_chain->to_chain)) + while(ple != NULL) { memset(cmd_buf, 0x0, CMD_BUFSIZE); - snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_OUT_RULE_ARGS, + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_RULE_ARGS, opts->fw_config->fw_command, - out_chain->table, - out_chain->to_chain, + in_chain->table, + in_chain->to_chain, ple->proto, spadat->use_src_ip, ple->port, exp_ts, - out_chain->target + in_chain->target ); //--DSS tmp -//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf); +//fprintf(stderr, "ADD CMD: %s\n", cmd_buf); res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); if(EXTCMD_IS_SUCCESS(res)) { - log_msg(LOG_INFO, "Added OUTPUT Rule to %s for %s, %s expires at %u", - out_chain->to_chain, spadat->use_src_ip, + log_msg(LOG_INFO, "Added Rule to %s for %s, %s expires at %u", + in_chain->to_chain, spadat->use_src_ip, spadat->spa_message_remain, exp_ts ); - out_chain->active_rules++; + in_chain->active_rules++; /* Reset the next expected expire time for this chain if it * is warranted. */ - if(out_chain->next_expire < now || exp_ts < out_chain->next_expire) - out_chain->next_expire = exp_ts; + if(in_chain->next_expire < now || exp_ts < in_chain->next_expire) + in_chain->next_expire = exp_ts; } else parse_extcmd_error(res, status, err); + /* If we have to make an corresponding OUTPUT rule if out_chain target + * is not NULL. + */ + if(out_chain->to_chain != NULL && strlen(out_chain->to_chain)) + { + memset(cmd_buf, 0x0, CMD_BUFSIZE); + + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_OUT_RULE_ARGS, + opts->fw_config->fw_command, + out_chain->table, + out_chain->to_chain, + ple->proto, + spadat->use_src_ip, + ple->port, + exp_ts, + out_chain->target + ); + +//--DSS tmp +//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf); + res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); + if(EXTCMD_IS_SUCCESS(res)) + { + log_msg(LOG_INFO, "Added OUTPUT Rule to %s for %s, %s expires at %u", + out_chain->to_chain, spadat->use_src_ip, + spadat->spa_message_remain, exp_ts + ); + + out_chain->active_rules++; + + /* Reset the next expected expire time for this chain if it + * is warranted. + */ + if(out_chain->next_expire < now || exp_ts < out_chain->next_expire) + out_chain->next_expire = exp_ts; + } + else + parse_extcmd_error(res, status, err); + + } + + ple = ple->next; } - ple = ple->next; + /* Done with the port list for access rules. + */ + free_acc_port_list(port_list); + } - - /* Done with the port list for access rules. - */ - free_acc_port_list(port_list); - - /* Now see if we have NAT rules to create... - */ - if( spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG + /* NAT requests... */ + else if( spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG || spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG || spadat->message_type == FKO_NAT_ACCESS_MSG || spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG ) @@ -566,7 +580,7 @@ process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) opts->fw_config->fw_command, fwd_chain->table, fwd_chain->to_chain, - cproto, + fst_proto, spadat->use_src_ip, nat_ip, nat_port, @@ -604,9 +618,9 @@ process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) opts->fw_config->fw_command, dnat_chain->table, dnat_chain->to_chain, - cproto, + fst_proto, spadat->use_src_ip, - cport, + fst_port, exp_ts, dnat_chain->target, nat_ip, @@ -634,6 +648,69 @@ process_access_request(fko_srv_options_t *opts, spa_data_t *spadat) else parse_extcmd_error(res, status, err); } + + /* If SNAT (or MASQUERADE) is wanted, then we add those rules here as well. + */ + if(opts->config[CONF_ENABLE_IPT_SNAT] != NULL + && strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0) + { + memset(cmd_buf, 0x0, CMD_BUFSIZE); + + /* Setup some parameter depending on whether we are using SNAT + * or MASQUERADE. + */ + if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL + && strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "_CHANGEME_", 10)!=0) + { + /* Using static SNAT */ + snat_chain = &(opts->fw_config->chain[IPT_SNAT_ACCESS]); + snprintf(snat_target, SNAT_TARGET_BUFSIZE-1, + "--to-source %s:%i", opts->config[CONF_SNAT_TRANSLATE_IP], + fst_port); + } + else + { + /* Using MASQUERADE */ + snat_chain = &(opts->fw_config->chain[IPT_MASQUERADE_ACCESS]); + snprintf(snat_target, SNAT_TARGET_BUFSIZE-1, + "--to-ports %i", fst_port); + } + + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_SNAT_RULE_ARGS, + opts->fw_config->fw_command, + snat_chain->table, + snat_chain->to_chain, + fst_proto, + //spadat->use_src_ip, + nat_ip, + //fst_port, + nat_port, + exp_ts, + snat_chain->target, + snat_target + ); + +//--DSS tmp +fprintf(stderr, "ADD SNAT CMD: %s\n", cmd_buf); + res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status); + if(EXTCMD_IS_SUCCESS(res)) + { + log_msg(LOG_INFO, "Added Source NAT Rule to %s for %s, %s expires at %u", + snat_chain->to_chain, spadat->use_src_ip, + spadat->spa_message_remain, exp_ts + ); + + snat_chain->active_rules++; + + /* Reset the next expected expire time for this chain if it + * is warranted. + */ + if(snat_chain->next_expire < now || exp_ts < snat_chain->next_expire) + snat_chain->next_expire = exp_ts; + } + else + parse_extcmd_error(res, status, err); + } } return(res); @@ -663,7 +740,9 @@ check_firewall_rules(fko_srv_options_t *opts) */ for(i = 0; i < NUM_FWKNOP_ACCESS_TYPES; i++) { - /* Just in case we somehow lose track and fall out-of-whack. + /* Just in case we somehow lose track and fall out-of-whack, + * we be the hero and reset it to zero. + * (poet but don't know it :-o ) */ if(ch[i].active_rules < 0) ch[i].active_rules = 0; diff --git a/server/fw_util.h b/server/fw_util.h index 5e05406b..f8248a49 100644 --- a/server/fw_util.h +++ b/server/fw_util.h @@ -31,12 +31,15 @@ #define STANDARD_CMD_OUT_BUFSIZE 4096 +#define SNAT_TARGET_BUFSIZE 64 + /* iptables command args */ #define IPT_ADD_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s" #define IPT_ADD_OUT_RULE_ARGS "-t %s -A %s -p %i -d %s --sport %i -m comment --comment _exp_%u -j %s" #define IPT_ADD_FWD_RULE_ARGS "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment _exp_%u -j %s" #define IPT_ADD_DNAT_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s --to-destination %s:%i" +#define IPT_ADD_SNAT_RULE_ARGS "-t %s -A %s -p %i -d %s --dport %i -m comment --comment _exp_%u -j %s %s" #define IPT_DEL_RULE_ARGS "-t %s -D %s %i" #define IPT_NEW_CHAIN_ARGS "-t %s -N %s" #define IPT_FLUSH_CHAIN_ARGS "-t %s -F %s" @@ -50,7 +53,7 @@ */ void fw_initialize(fko_srv_options_t *opts); void fw_cleanup(void); -int process_access_request(fko_srv_options_t *opts, spa_data_t *spdat); +int process_spa_request(fko_srv_options_t *opts, spa_data_t *spdat); void check_firewall_rules(fko_srv_options_t *opts); #endif /* FW_UTIL_H */ diff --git a/server/fwknopd.conf b/server/fwknopd.conf index b0a783f9..ca4bace3 100644 --- a/server/fwknopd.conf +++ b/server/fwknopd.conf @@ -123,7 +123,7 @@ ENABLE_IPT_OUTPUT N; MAX_SNIFF_BYTES 1500; # Flush all existing rules in the fwknop chains at fwknop start time and/or -# exit time. They default to Y. +# exit time. They default to Y and it is recommended setting. # FLUSH_IPT_AT_INIT Y; FLUSH_IPT_AT_EXIT Y; @@ -251,50 +251,62 @@ IPT_EXEC_TRIES 1; #ENABLE_EXT_CMD_PREFIX N; #EXT_CMD_PREFIX FWKNOP_; -# fwknop uses the IPTables::ChainMgr module to add allow rules to a -# custom iptables chain "FWKNOP_INPUT". This chain is called from -# the INPUT chain, and by default no other iptables chains are used. -# However, additional chains can be added (say, if access needs to -# be allowed through the local system via the FORWARD chain) by -# altering the IPT_FORWARD_ACCESS variable below. For a discussion of -# the format followed by these keywords, read on: -# Specify chain names to which iptables blocking rules will be +# fwknopd adds allow rules to a custom iptables chain "FWKNOP_INPUT". +# This chain is called from the INPUT chain, and by default no other +# iptables chains are used. However, additional chains can be added +# (say, if access needs to be allowed through the local system via the +# FORWARD chain) by altering the IPT_FORWARD_ACCESS variable below. +# For a discussion of the format followed by these keywords, read on: +# +# Specify chain names to which iptables blocking rules will be # added with the IPT_INPUT_ACCESS and IPT_FORWARD_ACCESS keyword. # The format for these variables is: -# ,,,,, \ -# ,. -# "Target": Can be any legitimate iptables target, but should usually -# just be "DROP". -# "Direction": Can be "src", "dst", or "both", which correspond to the -# INPUT, OUTPUT, and FORWARD chains. -# "Table": Can be any iptables table, but the default is "filter". -# "From_chain": Is the chain from which packets will be jumped. -# "Jump_rule_position": Defines the position within the From_chain where -# the jump rule is added. -# "To_chain": Is the chain to which packets will be jumped. This is the -# main chain where fwknop rules are added. -# "Rule_position": Defines the position where rule are added within the -# To_chain. # -IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1; +# ,,
,,,\ +# ,. +# +# "Target": +# Can be any legitimate iptables target, but should usually just be "DROP". +# +# "Direction": +# Can be "src", "dst", or "both", which correspond to the INPUT, OUTPUT, +# and FORWARD chains. +# +# "Table": +# Can be any iptables table, but the default is "filter". +# +# "From_chain": +# Is the chain from which packets will be jumped. +# +# "Jump_rule_position": +# Defines the position within the From_chain where the jump rule is added. +# +# "To_chain": +# Is the chain to which packets will be jumped. This is the main chain +# where fwknop rules are added. +# +# "Rule_position": +# Defines the position where rule are added within the To_chain. +# +IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1; # The IPT_OUTPUT_ACCESS variable is only used if ENABLE_IPT_OUTPUT is enabled # -IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1; +IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1; # The IPT_FORWARD_ACCESS variable is only used if ENABLE_IPT_FORWARDING is # enabled. # -IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1; -IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1; +IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1; +IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1; # The IPT_SNAT_ACCESS variable is not used unless both ENABLE_IPT_SNAT and # ENABLE_IPT_FORWARDING are enabled. Also, the external static IP must be # set with the SNAT_TRANSLATE_IP variable. The default is to use the # IPT_MASQUERADE_ACCESS variable. # -IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; -IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; +IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; +IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1; # Directories # diff --git a/server/incoming_spa.c b/server/incoming_spa.c index b670a315..84c6ab0a 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -240,8 +240,16 @@ incoming_spa(fko_srv_options_t *opts) */ res = get_spa_data_fields(ctx, &spadat); - spadat.fw_access_timeout = (acc->fw_access_timeout > 0) - ? acc->fw_access_timeout : DEF_FW_ACCESS_TIMEOUT; + /* Figure out what our timeout will be. If it is specified in the SPA + * data, then use that. If not, try the FW_ACCESS_TIMEOUT from the + * access.conf file (if there is one). Otherwise use the default. + */ + if(spadat.client_timeout > 0) + spadat.fw_access_timeout = spadat.client_timeout; + else if(acc->fw_access_timeout > 0) + spadat.fw_access_timeout = acc->fw_access_timeout; + else + spadat.fw_access_timeout = DEF_FW_ACCESS_TIMEOUT; if(res != FKO_SUCCESS) { @@ -364,7 +372,7 @@ incoming_spa(fko_srv_options_t *opts) /* If we are here we will at least need to have the base access. So we * can go ahead an generate that now. */ - res = process_access_request(opts, &spadat); + res = process_spa_request(opts, &spadat); #if 0 if(res != FKO_SUCCESS)