[server] Add FORWARD_ALL access.conf wildcard
This is a significant commit that allows iptables firewalls to be used as an "SPA gateway" for all ports/protocols upon providing a valid SPA packet. Additional commits will be made to extend this capability, but this commit adds two new access.conf keywords: FORWARD_ALL and DISABLE_DNAT. These are used in conjunction to add ACCEPT rules for all ports/protocols in the FORWARD chain, and also disable DNAT rules at the same time. Then, by buildling the SNAT chain to provide translation for an internal network (where an SPA cliet is located), but DROP all forwarded traffic by default at the same time, SPA can be used to gain access to the internet. So, this would allow, say, an RFC 1918 internal network to have IP's assigned via DHCP but they wouldn't be able to access the internet before sending a SPA packet to the gateway. This scenario was suggested by spartan1833 to the fwknop list and tracked via github issue 131. Additional commits will be made to fully support this feature.
This commit is contained in:
parent
d148fb091a
commit
6b7a3bbdae
@ -139,6 +139,8 @@ enum {
|
||||
#define FKO_DEFAULT_PORT 62201
|
||||
#define DEFAULT_NAT_PORT 55000
|
||||
#define MIN_HIGH_PORT 10000 /* sensible minimum for SPA dest port */
|
||||
#define ANY_PORT 0 /* used as a wildcard */
|
||||
#define ANY_PROTO 0 /* used as a wildcard */
|
||||
#define MAX_SERVER_STR_LEN 50
|
||||
#define MAX_ICMP_TYPE 40
|
||||
#define MAX_ICMP_CODE 15
|
||||
|
||||
@ -1134,10 +1134,11 @@ acc_data_is_valid(struct passwd *user_pw, acc_stanza_t * const acc)
|
||||
}
|
||||
}
|
||||
|
||||
if((acc->force_snat == 1 || acc->force_masquerade == 1) && acc->force_nat == 0)
|
||||
if((acc->force_snat == 1 || acc->force_masquerade == 1)
|
||||
&& acc->force_nat == 0 && acc->disable_dnat == 0)
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[*] FORCE_SNAT/FORCE_MASQUERADE implies FORCE_NAT must also be used for access stanza source: '%s'",
|
||||
"[*] FORCE_SNAT/FORCE_MASQUERADE implies FORCE_NAT or DISABLE_DNAT must also be used for stanza source: '%s'",
|
||||
acc->source
|
||||
);
|
||||
return(0);
|
||||
@ -1707,6 +1708,14 @@ parse_access_file(fko_srv_options_t *opts)
|
||||
add_acc_bool(&(curr_acc->force_masquerade), val);
|
||||
add_acc_bool(&(curr_acc->force_snat), val);
|
||||
}
|
||||
else if(CONF_VAR_IS(var, "DISABLE_DNAT"))
|
||||
{
|
||||
add_acc_bool(&(curr_acc->disable_dnat), val);
|
||||
}
|
||||
else if(CONF_VAR_IS(var, "FORWARD_ALL"))
|
||||
{
|
||||
add_acc_bool(&(curr_acc->forward_all), val);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
@ -1941,6 +1950,8 @@ dump_access_list(const fko_srv_options_t *opts)
|
||||
" FORCE_NAT (port): %d\n"
|
||||
" FORCE_SNAT (ip): %s\n"
|
||||
" FORCE_MASQUERADE: %s\n"
|
||||
" DISABLE_DNAT: %s\n"
|
||||
" FORWARD_ALL: %s\n"
|
||||
" ACCESS_EXPIRE: %s" /* asctime() adds a newline */
|
||||
" GPG_HOME_DIR: %s\n"
|
||||
" GPG_EXE: %s\n"
|
||||
@ -1972,6 +1983,8 @@ dump_access_list(const fko_srv_options_t *opts)
|
||||
acc->force_nat ? acc->force_nat_port : 0,
|
||||
acc->force_snat ? acc->force_snat_ip : "<not set>",
|
||||
acc->force_masquerade ? "Yes" : "No",
|
||||
acc->disable_dnat ? "Yes" : "No",
|
||||
acc->forward_all ? "Yes" : "No",
|
||||
(acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "<not set>\n",
|
||||
(acc->gpg_home_dir == NULL) ? "<not set>" : acc->gpg_home_dir,
|
||||
(acc->gpg_exe == NULL) ? "<not set>" : acc->gpg_exe,
|
||||
|
||||
@ -122,11 +122,14 @@ rule_exists_no_chk_support(const fko_srv_options_t * const opts,
|
||||
* primary search method
|
||||
*/
|
||||
if(search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, exp_ts_search, &pid_status, opts)
|
||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, proto_search, &pid_status, opts)
|
||||
&& (proto == ANY_PROTO) ? 1 :
|
||||
search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, proto_search, &pid_status, opts)
|
||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, srcip_search, &pid_status, opts)
|
||||
&& (dstip == NULL) ? 1 : search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, dstip_search, &pid_status, opts)
|
||||
&& (dstip == NULL) ? 1 :
|
||||
search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, dstip_search, &pid_status, opts)
|
||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, target_search, &pid_status, opts)
|
||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, port_search, &pid_status, opts))
|
||||
&& (port == ANY_PORT) ? 1 :
|
||||
search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, port_search, &pid_status, opts))
|
||||
rule_exists = 1;
|
||||
|
||||
if(rule_exists)
|
||||
@ -179,7 +182,7 @@ static int
|
||||
rule_exists(const fko_srv_options_t * const opts,
|
||||
const struct fw_chain * const fwc, const char * const rule,
|
||||
const unsigned int proto, const char * const srcip,
|
||||
const char * const dstip, const unsigned int port,
|
||||
const char * const dstip, const unsigned int port,
|
||||
const unsigned int exp_ts)
|
||||
{
|
||||
int rule_exists = 0;
|
||||
@ -187,7 +190,8 @@ rule_exists(const fko_srv_options_t * const opts,
|
||||
if(have_ipt_chk_support == 1)
|
||||
rule_exists = rule_exists_chk_support(opts, fwc->to_chain, rule);
|
||||
else
|
||||
rule_exists = rule_exists_no_chk_support(opts, fwc, proto, srcip, (opts->fw_config->use_destination ? dstip : NULL), port, exp_ts);
|
||||
rule_exists = rule_exists_no_chk_support(opts, fwc, proto, srcip,
|
||||
(opts->fw_config->use_destination ? dstip : NULL), port, exp_ts);
|
||||
|
||||
if(rule_exists == 1)
|
||||
log_msg(LOG_DEBUG, "rule_exists() Rule : '%s' in %s already exists",
|
||||
@ -944,7 +948,8 @@ create_rule(const fko_srv_options_t * const opts,
|
||||
|
||||
zero_cmd_buffers();
|
||||
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s -A %s %s", opts->fw_config->fw_command, fw_chain, fw_rule);
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s -A %s %s",
|
||||
opts->fw_config->fw_command, fw_chain, fw_rule);
|
||||
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
@ -955,7 +960,8 @@ create_rule(const fko_srv_options_t * const opts,
|
||||
|
||||
if(EXTCMD_IS_SUCCESS(res))
|
||||
{
|
||||
log_msg(LOG_DEBUG, "create_rule() Rule: '%s' added to %s", fw_rule, fw_chain);
|
||||
log_msg(LOG_DEBUG, "create_rule() Rule: '%s' added to %s",
|
||||
fw_rule, fw_chain);
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
@ -1005,7 +1011,8 @@ ipt_rule(const fko_srv_options_t * const opts,
|
||||
if(create_rule(opts, chain->to_chain, rule_buf))
|
||||
{
|
||||
log_msg(LOG_INFO, "Added %s rule to %s for %s -> %s %s, expires at %u",
|
||||
msg, chain->to_chain, srcip, dstip, access_msg, exp_ts
|
||||
msg, chain->to_chain, srcip, (dstip == NULL) ? IPT_ANY_IP : dstip,
|
||||
access_msg, exp_ts
|
||||
);
|
||||
|
||||
chain->active_rules++;
|
||||
@ -1136,7 +1143,8 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
return res;
|
||||
}
|
||||
|
||||
nat_port = strtol_wrapper(ndx+1, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
|
||||
nat_port = strtol_wrapper(ndx+1, 0, MAX_PORT,
|
||||
NO_EXIT_UPON_ERR, &is_err);
|
||||
if(is_err != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_INFO, "Invalid NAT port in SPA message");
|
||||
@ -1156,15 +1164,35 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
}
|
||||
else if(strlen(fwd_chain->to_chain))
|
||||
{
|
||||
/* Make our FORWARD and NAT rules, and make sure the
|
||||
* required chain and jump rule exists
|
||||
*/
|
||||
ipt_rule(opts, NULL, IPT_FWD_RULE_ARGS, spadat->use_src_ip,
|
||||
nat_ip, fst_proto, nat_port, fwd_chain, exp_ts, now, "FORWARD",
|
||||
spadat->spa_message_remain);
|
||||
if(acc->forward_all)
|
||||
{
|
||||
|
||||
memset(rule_buf, 0, CMD_BUFSIZE);
|
||||
|
||||
snprintf(rule_buf, CMD_BUFSIZE-1, IPT_FWD_ALL_RULE_ARGS,
|
||||
fwd_chain->table,
|
||||
spadat->use_src_ip,
|
||||
exp_ts,
|
||||
fwd_chain->target
|
||||
);
|
||||
|
||||
/* Make a global ACCEPT rule for all ports/protocols
|
||||
*/
|
||||
ipt_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||
NULL, ANY_PROTO, ANY_PORT, fwd_chain, exp_ts, now,
|
||||
"FORWARD ALL", "*/*");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make our FORWARD and NAT access rules
|
||||
*/
|
||||
ipt_rule(opts, NULL, IPT_FWD_RULE_ARGS, spadat->use_src_ip,
|
||||
nat_ip, fst_proto, nat_port, fwd_chain, exp_ts, now,
|
||||
"FORWARD", spadat->spa_message_remain);
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen(dnat_chain->to_chain))
|
||||
if(!acc->disable_dnat && strlen(dnat_chain->to_chain))
|
||||
{
|
||||
memset(rule_buf, 0, CMD_BUFSIZE);
|
||||
|
||||
@ -1180,7 +1208,7 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
nat_port
|
||||
);
|
||||
|
||||
ipt_rule(opts, rule_buf, IPT_DNAT_RULE_ARGS, spadat->use_src_ip,
|
||||
ipt_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||
(fwc.use_destination ? spadat->pkt_destination_ip : IPT_ANY_IP),
|
||||
fst_proto, fst_port, dnat_chain, exp_ts, now, "DNAT",
|
||||
spadat->spa_message_remain);
|
||||
@ -1235,7 +1263,7 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
snat_target
|
||||
);
|
||||
|
||||
ipt_rule(opts, rule_buf, IPT_SNAT_RULE_ARGS, spadat->use_src_ip,
|
||||
ipt_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||
NULL, fst_proto, nat_port, snat_chain, exp_ts, now, "SNAT",
|
||||
spadat->spa_message_remain);
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
#define IPT_RULE_ARGS "-t %s -p %i -s %s -d %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s" SH_REDIR
|
||||
#define IPT_OUT_RULE_ARGS "-t %s -p %i -d %s -s %s --sport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s" SH_REDIR
|
||||
#define IPT_FWD_RULE_ARGS "-t %s -p %i -s %s -d %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s" SH_REDIR
|
||||
#define IPT_FWD_ALL_RULE_ARGS "-t %s -s %s -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s" SH_REDIR
|
||||
#define IPT_DNAT_RULE_ARGS "-t %s -p %i -s %s -d %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s --to-destination %s:%i" SH_REDIR
|
||||
#define IPT_SNAT_RULE_ARGS "-t %s -p %i -d %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s %s" SH_REDIR
|
||||
#define IPT_TMP_COMMENT_ARGS "-t %s -I %s %i -s 127.0.0.2 -m comment --comment " TMP_COMMENT " -j %s" SH_REDIR
|
||||
|
||||
@ -389,15 +389,14 @@ typedef struct acc_stanza
|
||||
int expired;
|
||||
int encryption_mode;
|
||||
|
||||
/* DNAT parameters
|
||||
/* NAT parameters
|
||||
*/
|
||||
unsigned char force_nat;
|
||||
char *force_nat_ip;
|
||||
char *force_nat_proto;
|
||||
unsigned int force_nat_port;
|
||||
|
||||
/* SNAT parameters
|
||||
*/
|
||||
unsigned char disable_dnat;
|
||||
unsigned char forward_all;
|
||||
unsigned char force_snat;
|
||||
char *force_snat_ip;
|
||||
unsigned char force_masquerade;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user