diff --git a/Makefile.am b/Makefile.am index eb9218d1..89e4a4d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,7 +145,6 @@ EXTRA_DIST = \ test/conf/expired_epoch_stanza_access.conf \ test/conf/expired_stanza_access.conf \ test/conf/force_nat_access.conf \ - test/conf/force_nat_access.conf \ test/conf/future_expired_stanza_access.conf \ test/conf/fuzzing_open_ports_access.conf \ test/conf/fuzzing_restrict_ports_access.conf \ @@ -186,6 +185,8 @@ EXTRA_DIST = \ test/conf/hmac_simple_keys_access.conf \ test/conf/hmac_sha256_open_ports_access.conf \ test/conf/hmac_force_nat_access.conf \ + test/conf/hmac_force_snat_access.conf \ + test/conf/hmac_force_masq_access.conf \ test/conf/hmac_no_b64_cygwin_access.conf \ test/conf/fwknoprc_default_hmac_base64_key \ test/conf/fwknoprc_hmac_key2 \ diff --git a/server/access.c b/server/access.c index 88699f72..d504a3dd 100644 --- a/server/access.c +++ b/server/access.c @@ -992,6 +992,15 @@ acc_data_is_valid(acc_stanza_t * const acc) return(0); } + if(acc->force_masquerade == 1 && acc->force_nat == 0) + { + log_msg(LOG_ERR, + "[*] FORCE_MASQUERADE implies FORCE_NAT must also be used for access stanza source: '%s'", + acc->source + ); + return(0); + } + if(acc->require_source_address == 0) { log_msg(LOG_INFO, @@ -1395,6 +1404,11 @@ parse_access_file(fko_srv_options_t *opts) clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); #endif } + else if(CONF_VAR_IS(var, "FORCE_MASQUERADE")) + { + add_acc_bool(&(curr_acc->force_masquerade), val); + add_acc_bool(&(curr_acc->force_snat), val); + } else { log_msg(LOG_ERR, @@ -1643,6 +1657,8 @@ dump_access_list(const fko_srv_options_t *opts) " FORCE_NAT (ip): %s\n" " FORCE_NAT (proto): %s\n" " FORCE_NAT (port): %d\n" + " FORCE_SNAT (ip): %s\n" + " FORCE_MASQUERADE: %s\n" " ACCESS_EXPIRE: %s" /* asctime() adds a newline */ " GPG_HOME_DIR: %s\n" " GPG_DECRYPT_ID: %s\n" @@ -1669,6 +1685,8 @@ dump_access_list(const fko_srv_options_t *opts) acc->force_nat ? acc->force_nat_ip : "", acc->force_nat && acc->force_nat_proto != NULL ? acc->force_nat_proto : "", acc->force_nat ? acc->force_nat_port : 0, + acc->force_snat ? acc->force_snat_ip : "", + acc->force_masquerade ? "Yes" : "No", (acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "\n", (acc->gpg_home_dir == NULL) ? "" : acc->gpg_home_dir, (acc->gpg_decrypt_id == NULL) ? "" : acc->gpg_decrypt_id, diff --git a/server/fw_util_iptables.c b/server/fw_util_iptables.c index 5460430a..27702769 100644 --- a/server/fw_util_iptables.c +++ b/server/fw_util_iptables.c @@ -1272,6 +1272,14 @@ process_spa_request(const fko_srv_options_t * const opts, "--to-source %s:%i", acc->force_snat_ip, fst_port); snat_chain_num = IPT_SNAT_ACCESS; } + else if(acc->force_snat && acc->force_masquerade) + { + /* Using MASQUERADE */ + snat_chain = &(opts->fw_config->chain[IPT_MASQUERADE_ACCESS]); + snprintf(snat_target, SNAT_TARGET_BUFSIZE-1, + "--to-ports %i", fst_port); + snat_chain_num = IPT_MASQUERADE_ACCESS; + } else if((opts->config[CONF_SNAT_TRANSLATE_IP] != NULL) && is_valid_ipv4_addr(opts->config[CONF_SNAT_TRANSLATE_IP])) { diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index b06c8490..fffb89e4 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -333,6 +333,7 @@ typedef struct acc_stanza */ unsigned char force_snat; char *force_snat_ip; + unsigned char force_masquerade; struct acc_stanza *next; } acc_stanza_t; diff --git a/test/test-fwknop.pl b/test/test-fwknop.pl index 0a6905c6..b2c886e6 100755 --- a/test/test-fwknop.pl +++ b/test/test-fwknop.pl @@ -80,6 +80,7 @@ our %cf = ( 'force_nat_access' => "$conf_dir/force_nat_access.conf", 'hmac_force_nat_access' => "$conf_dir/hmac_force_nat_access.conf", 'hmac_force_snat_access' => "$conf_dir/hmac_force_snat_access.conf", + 'hmac_force_masq_access' => "$conf_dir/hmac_force_masq_access.conf", 'cmd_access' => "$conf_dir/cmd_access.conf", 'local_nat' => "$conf_dir/local_nat_fwknopd.conf", 'no_flush_init' => "$conf_dir/no_flush_init_fwknopd.conf", diff --git a/test/tests/rijndael_hmac.pl b/test/tests/rijndael_hmac.pl index 3d65639e..c3003d15 100644 --- a/test/tests/rijndael_hmac.pl +++ b/test/tests/rijndael_hmac.pl @@ -892,6 +892,45 @@ 'key_file' => $cf{'rc_hmac_b64_key'}, 'iptables_rm_chains_after_server_start' => $YES, }, + { + 'category' => 'Rijndael+HMAC', + 'subcategory' => 'client+server', + 'detail' => "force MASQ $force_snat_host (tcp/22)", + 'function' => \&spa_cycle, + 'cmdline' => $default_client_args, + 'cmdline' => "$default_client_args_no_get_key --rc-file " . + $cf{'rc_hmac_b64_key'}, + 'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'snat_no_translate_ip'} -a $cf{'hmac_force_masq_access'} " . + "-d $default_digest_file -p $default_pid_file $intf_str", + 'server_positive_output_matches' => [qr/DNAT\s.*\*\/\sto\:$force_nat_host2\:22/i, + qr/MASQUERADE\s.*\s$force_nat_host2\s.*\smasq\sports\:\s22/], + 'server_negative_output_matches' => [qr/\*\/\sto\:$internal_nat_host\:22/i, + qr/\*\/\sto\:$force_nat_host\:22/i], + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'server_conf' => $cf{'snat_no_translate_ip'}, + 'key_file' => $cf{'rc_hmac_b64_key'}, + }, + { + 'category' => 'Rijndael+HMAC', + 'subcategory' => 'client+server', + 'detail' => "force MASQ $force_snat_host (ipt flush)", + 'function' => \&spa_cycle, + 'cmdline' => $default_client_args, + 'cmdline' => "$default_client_args_no_get_key --rc-file " . + $cf{'rc_hmac_b64_key'}, + 'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'snat_no_translate_ip'} -a $cf{'hmac_force_masq_access'} " . + "-d $default_digest_file -p $default_pid_file $intf_str", + 'server_positive_output_matches' => [qr/DNAT\s.*\*\/\sto\:$force_nat_host2\:22/i, + qr/MASQUERADE\s.*\s$force_nat_host2\s.*\smasq\sports\:\s22/], + 'server_negative_output_matches' => [qr/\*\/\sto\:$internal_nat_host\:22/i, + qr/\*\/\sto\:$force_nat_host\:22/i], + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'server_conf' => $cf{'snat_no_translate_ip'}, + 'key_file' => $cf{'rc_hmac_b64_key'}, + 'iptables_rm_chains_after_server_start' => $YES, + }, { 'category' => 'Rijndael+HMAC', 'subcategory' => 'client+server',