[server] Added FORCE_SNAT to access.conf stanzas.
Added FORCE_SNAT to the access.conf file so that per-access stanza SNAT criteria can be specified for SPA access.
This commit is contained in:
parent
d7aa820e33
commit
e0114e60c2
@ -29,6 +29,8 @@ fwknop-2.5.2 (//2013):
|
||||
- [server] Bug fix for SPA NAT modes on iptables firewalls to ensure that
|
||||
custom fwknop chains are re-created if they get deleted out from under
|
||||
the running fwknopd instance.
|
||||
- [server] Added FORCE_SNAT to the access.conf file so that per-access
|
||||
stanza SNAT criteria can be specified for SPA access.
|
||||
- [test suite] added --gdb-test to allow a previously executed fwknop
|
||||
or fwknopd command to be sent through gdb with the same command line
|
||||
args as the test suite used. This is for convenience to rapidly allow
|
||||
|
||||
@ -443,6 +443,16 @@ directive starts a new stanza.
|
||||
for each stanza in the access.conf file. This way, multiple external
|
||||
users can each directly access only one internal system per SPA key.
|
||||
|
||||
*FORCE_SNAT* '<IP>'::
|
||||
For any valid SPA packet, add an SNAT rule in addition to any DNAT rule
|
||||
created with a corresponding (required) FORCE_NAT variable. This is
|
||||
analogous to SNAT_TRANSLATE_IP from the '@sysconfdir@/fwknop/fwknopd.conf'' file
|
||||
except that it is per access stanza and overrides any value set with
|
||||
SNAT_TRANSLATE_IP. This is useful for situations where an incoming NAT'd
|
||||
connection may be otherwise unanswerable due to routing constraints (i.e.
|
||||
the system receiving the SPA authenticated connection has a default route
|
||||
to a different device than the SPA system itself).
|
||||
|
||||
*GPG_HOME_DIR* '<path>'::
|
||||
Define the path to the GnuPG directory to be used by the *fwknopd*
|
||||
server. If this keyword is not specified within '@sysconfdir@/fwknop/access.conf' then
|
||||
|
||||
@ -165,7 +165,6 @@ add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *v
|
||||
|
||||
if (sscanf(val, "%15s %5u", ip_str, &curr_acc->force_nat_port) != 2)
|
||||
{
|
||||
|
||||
log_msg(LOG_ERR,
|
||||
"[*] Fatal: invalid FORCE_NAT arg '%s', need <IP> <PORT>",
|
||||
val
|
||||
@ -192,6 +191,32 @@ add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *v
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
add_acc_force_snat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *val)
|
||||
{
|
||||
char ip_str[MAX_IPV4_STR_LEN] = {0};
|
||||
|
||||
if (sscanf(val, "%15s", ip_str) != 1)
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[*] Fatal: invalid FORCE_SNAT arg '%s', need <IP>", val);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(! is_valid_ipv4_addr(ip_str))
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[*] Fatal: invalid FORCE_NAT IP '%s'", ip_str);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
curr_acc->force_snat = 1;
|
||||
add_acc_string(&(curr_acc->force_snat_ip), ip_str);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Take an IP or Subnet/Mask and convert it to mask for later
|
||||
@ -680,6 +705,9 @@ free_acc_stanza_data(acc_stanza_t *acc)
|
||||
if(acc->force_nat_ip != NULL)
|
||||
free(acc->force_nat_ip);
|
||||
|
||||
if(acc->force_nat_ip != NULL)
|
||||
free(acc->force_snat_ip);
|
||||
|
||||
if(acc->key != NULL)
|
||||
{
|
||||
zero_buf_wrapper(acc->key, acc->key_len);
|
||||
@ -955,6 +983,15 @@ acc_data_is_valid(acc_stanza_t * const acc)
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->force_snat == 1 && acc->force_nat == 0)
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[*] FORCE_SNAT 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,
|
||||
@ -1338,6 +1375,24 @@ parse_access_file(fko_srv_options_t *opts)
|
||||
"[*] FORCE_NAT not supported.");
|
||||
fclose(file_ptr);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
else if(CONF_VAR_IS(var, "FORCE_SNAT"))
|
||||
{
|
||||
#if FIREWALL_IPTABLES
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1) !=0 )
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[*] FORCE_SNAT_NAT requires ENABLE_IPT_FORWARDING to be enabled in fwknopd.conf");
|
||||
fclose(file_ptr);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
add_acc_force_snat(opts, curr_acc, val);
|
||||
#else
|
||||
log_msg(LOG_ERR,
|
||||
"[*] FORCE_SNAT not supported.");
|
||||
fclose(file_ptr);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@ -961,7 +961,7 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
struct fw_chain * const dnat_chain = &(opts->fw_config->chain[IPT_DNAT_ACCESS]);
|
||||
struct fw_chain *snat_chain; /* We assign this later (if we need to). */
|
||||
|
||||
int res = 0, is_err;
|
||||
int res = 0, is_err, snat_chain_num = 0;
|
||||
time_t now;
|
||||
unsigned int exp_ts;
|
||||
|
||||
@ -1260,29 +1260,27 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
|
||||
/* If SNAT (or MASQUERADE) is wanted, then we add those rules here as well.
|
||||
*/
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
|
||||
if(acc->force_snat || strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
|
||||
{
|
||||
/* Setup some parameter depending on whether we are using SNAT
|
||||
* or MASQUERADE.
|
||||
/* Add SNAT or MASQUERADE rules.
|
||||
*/
|
||||
if((opts->config[CONF_SNAT_TRANSLATE_IP] != NULL)
|
||||
&& strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "__CHANGEME__", 10)!=0)
|
||||
if(acc->force_snat && is_valid_ipv4_addr(acc->force_snat_ip))
|
||||
{
|
||||
/* Using static SNAT */
|
||||
snat_chain = &(opts->fw_config->chain[IPT_SNAT_ACCESS]);
|
||||
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
|
||||
"--to-source %s:%i", acc->force_snat_ip, fst_port);
|
||||
snat_chain_num = IPT_SNAT_ACCESS;
|
||||
}
|
||||
else if((opts->config[CONF_SNAT_TRANSLATE_IP] != NULL)
|
||||
&& is_valid_ipv4_addr(opts->config[CONF_SNAT_TRANSLATE_IP]))
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* Check to make sure that the jump rules exist for each
|
||||
* required chain
|
||||
*/
|
||||
if(chain_exists(opts, IPT_SNAT_ACCESS) == 0)
|
||||
create_chain(opts, IPT_SNAT_ACCESS);
|
||||
|
||||
if(jump_rule_exists(opts, IPT_SNAT_ACCESS) == 0)
|
||||
add_jump_rule(opts, IPT_SNAT_ACCESS);
|
||||
|
||||
snat_chain_num = IPT_SNAT_ACCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1290,17 +1288,15 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
snat_chain = &(opts->fw_config->chain[IPT_MASQUERADE_ACCESS]);
|
||||
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
|
||||
"--to-ports %i", fst_port);
|
||||
|
||||
/* Check to make sure that the jump rules exist for each
|
||||
* required chain
|
||||
*/
|
||||
if(chain_exists(opts, IPT_MASQUERADE_ACCESS) == 0)
|
||||
create_chain(opts, IPT_MASQUERADE_ACCESS);
|
||||
|
||||
if(jump_rule_exists(opts, IPT_MASQUERADE_ACCESS) == 0)
|
||||
add_jump_rule(opts, IPT_MASQUERADE_ACCESS);
|
||||
snat_chain_num = IPT_MASQUERADE_ACCESS;
|
||||
}
|
||||
|
||||
if(chain_exists(opts, snat_chain_num) == 0)
|
||||
create_chain(opts, snat_chain_num);
|
||||
|
||||
if(jump_rule_exists(opts, snat_chain_num) == 0)
|
||||
add_jump_rule(opts, snat_chain_num);
|
||||
|
||||
memset(rule_buf, 0, CMD_BUFSIZE);
|
||||
|
||||
snprintf(rule_buf, CMD_BUFSIZE-1, IPT_SNAT_RULE_ARGS,
|
||||
|
||||
@ -321,10 +321,19 @@ typedef struct acc_stanza
|
||||
time_t access_expire_time;
|
||||
int expired;
|
||||
int encryption_mode;
|
||||
|
||||
/* DNAT parameters
|
||||
*/
|
||||
unsigned char force_nat;
|
||||
char *force_nat_ip;
|
||||
char *force_nat_proto;
|
||||
unsigned int force_nat_port;
|
||||
|
||||
/* SNAT parameters
|
||||
*/
|
||||
unsigned char force_snat;
|
||||
char *force_snat_ip;
|
||||
|
||||
struct acc_stanza *next;
|
||||
} acc_stanza_t;
|
||||
|
||||
|
||||
@ -79,6 +79,7 @@ our %cf = (
|
||||
'invalid_ipt_input_chain6' => "$conf_dir/invalid_ipt_input_chain_6_fwknopd.conf",
|
||||
'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",
|
||||
'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",
|
||||
@ -186,6 +187,8 @@ our $fake_ip = '127.0.0.2';
|
||||
our $spoof_ip = '1.2.3.4';
|
||||
our $internal_nat_host = '192.168.1.2';
|
||||
our $force_nat_host = '192.168.1.123';
|
||||
our $force_nat_host2 = '123.4.4.4';
|
||||
our $force_snat_host = '33.3.3.3';
|
||||
our $default_spa_port = 62201;
|
||||
our $non_std_spa_port = 12345;
|
||||
|
||||
|
||||
@ -846,13 +846,52 @@
|
||||
$cf{'rc_hmac_b64_key'},
|
||||
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_force_nat_access'} " .
|
||||
"-d $default_digest_file -p $default_pid_file $intf_str",
|
||||
'server_positive_output_matches' => [qr/\sto\:$force_nat_host\:22/i],
|
||||
'server_negative_output_matches' => [qr/\sto\:$internal_nat_host\:22/i],
|
||||
'server_positive_output_matches' => [qr/\*\/\sto\:$force_nat_host\:22/i],
|
||||
'server_negative_output_matches' => [qr/\*\/\sto\:$internal_nat_host\:22/i],
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
'server_conf' => $cf{'nat'},
|
||||
'key_file' => $cf{'rc_hmac_b64_key'},
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "force SNAT $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'} -a $cf{'hmac_force_snat_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/SNAT\s.*\*\/\sto\:$force_snat_host\:22/],
|
||||
'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'},
|
||||
'key_file' => $cf{'rc_hmac_b64_key'},
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client+server',
|
||||
'detail' => "force SNAT $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'} -a $cf{'hmac_force_snat_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/SNAT\s.*\*\/\sto\:$force_snat_host\:22/],
|
||||
'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'},
|
||||
'key_file' => $cf{'rc_hmac_b64_key'},
|
||||
'iptables_rm_chains_after_server_start' => $YES,
|
||||
},
|
||||
{
|
||||
'category' => 'Rijndael+HMAC',
|
||||
'subcategory' => 'client+server',
|
||||
@ -863,8 +902,8 @@
|
||||
$cf{'rc_hmac_b64_key'},
|
||||
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_force_nat_access'} " .
|
||||
"-d $default_digest_file -p $default_pid_file $intf_str",
|
||||
'server_positive_output_matches' => [qr/\sto\:$force_nat_host\:22/i],
|
||||
'server_negative_output_matches' => [qr/\sto\:$internal_nat_host\:22/i],
|
||||
'server_positive_output_matches' => [qr/\*\/\sto\:$force_nat_host\:22/i],
|
||||
'server_negative_output_matches' => [qr/\*\/\sto\:$internal_nat_host\:22/i],
|
||||
'fw_rule_created' => $NEW_RULE_REQUIRED,
|
||||
'fw_rule_removed' => $NEW_RULE_REMOVED,
|
||||
'server_conf' => $cf{'nat'},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user