Implement "global" mode for ipfw nat. It is similar to natd(8)
"globalport" option for multiple NAT instances. If ipfw rule contains "global" keyword instead of nat_number, then for each outgoing packet ipfw_nat looks up translation state in all configured nat instances. If an entry is found, packet aliased according to that entry, otherwise packet is passed unchanged. User can specify "skip_global" option in NAT configuration to exclude an instance from the lookup in global mode. PR: kern/157867 Submitted by: Alexander V. Chernikov (previous version) Tested by: Eugene Grosbein
This commit is contained in:
parent
980ccceb94
commit
1875bbfe54
@ -1,7 +1,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 30, 2011
|
||||
.Dd June 14, 2011
|
||||
.Dt IPFW 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -2435,6 +2435,27 @@ Reset table of the packet aliasing engine on address change.
|
||||
Reverse the way libalias handles aliasing.
|
||||
.It Cm proxy_only
|
||||
Obey transparent proxy rules only, packet aliasing is not performed.
|
||||
.It Cm skip_global
|
||||
Skip instance in case of global state lookup (see below).
|
||||
.El
|
||||
.Pp
|
||||
Some specials value can be supplied instead of
|
||||
.Va nat_number:
|
||||
.Bl -tag -width indent
|
||||
.It Cm global
|
||||
Looks up translation state in all configured nat instances.
|
||||
If an entry is found, packet is aliased according to that entry.
|
||||
If no entry was found in any of the instances, packet is passed unchanged,
|
||||
and no new entry will be created.
|
||||
See section
|
||||
.Sx MULTIPLE INSTANCES
|
||||
in
|
||||
.Xr natd 8
|
||||
for more information.
|
||||
.It Cm tablearg
|
||||
Uses argument supplied in lookup table. See
|
||||
.Sx LOOKUP TABLES
|
||||
section below for more information on lookup tables.
|
||||
.El
|
||||
.Pp
|
||||
To let the packet continue after being (de)aliased, set the sysctl variable
|
||||
|
@ -1121,8 +1121,11 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
break;
|
||||
|
||||
case O_NAT:
|
||||
PRINT_UINT_ARG("nat ", cmd->arg1);
|
||||
break;
|
||||
if (cmd->arg1 != 0)
|
||||
PRINT_UINT_ARG("nat ", cmd->arg1);
|
||||
else
|
||||
printf("nat global");
|
||||
break;
|
||||
|
||||
case O_SETFIB:
|
||||
PRINT_UINT_ARG("setfib ", cmd->arg1);
|
||||
@ -2738,9 +2741,14 @@ ipfw_add(char *av[])
|
||||
break;
|
||||
|
||||
case TOK_NAT:
|
||||
action->opcode = O_NAT;
|
||||
action->len = F_INSN_SIZE(ipfw_insn_nat);
|
||||
goto chkarg;
|
||||
action->opcode = O_NAT;
|
||||
action->len = F_INSN_SIZE(ipfw_insn_nat);
|
||||
if (_substrcmp(*av, "global") == 0) {
|
||||
action->arg1 = 0;
|
||||
av++;
|
||||
break;
|
||||
} else
|
||||
goto chkarg;
|
||||
|
||||
case TOK_QUEUE:
|
||||
action->opcode = O_QUEUE;
|
||||
|
@ -178,6 +178,7 @@ enum tokens {
|
||||
TOK_DENY_INC,
|
||||
TOK_SAME_PORTS,
|
||||
TOK_UNREG_ONLY,
|
||||
TOK_SKIP_GLOBAL,
|
||||
TOK_RESET_ADDR,
|
||||
TOK_ALIAS_REV,
|
||||
TOK_PROXY_ONLY,
|
||||
|
@ -53,6 +53,7 @@ static struct _s_x nat_params[] = {
|
||||
{ "deny_in", TOK_DENY_INC },
|
||||
{ "same_ports", TOK_SAME_PORTS },
|
||||
{ "unreg_only", TOK_UNREG_ONLY },
|
||||
{ "skip_global", TOK_SKIP_GLOBAL },
|
||||
{ "reset", TOK_RESET_ADDR },
|
||||
{ "reverse", TOK_ALIAS_REV },
|
||||
{ "proxy_only", TOK_PROXY_ONLY },
|
||||
@ -628,6 +629,9 @@ print_nat_config(unsigned char *buf)
|
||||
} else if (n->mode & PKT_ALIAS_SAME_PORTS) {
|
||||
printf(" same_ports");
|
||||
n->mode &= ~PKT_ALIAS_SAME_PORTS;
|
||||
} else if (n->mode & PKT_ALIAS_SKIP_GLOBAL) {
|
||||
printf(" skip_global");
|
||||
n->mode &= ~PKT_ALIAS_SKIP_GLOBAL;
|
||||
} else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
|
||||
printf(" unreg_only");
|
||||
n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
|
||||
@ -746,10 +750,11 @@ ipfw_config_nat(int ac, char **av)
|
||||
case TOK_IP:
|
||||
case TOK_IF:
|
||||
ac1--; av1++;
|
||||
break;
|
||||
break;
|
||||
case TOK_ALOG:
|
||||
case TOK_DENY_INC:
|
||||
case TOK_SAME_PORTS:
|
||||
case TOK_SKIP_GLOBAL:
|
||||
case TOK_UNREG_ONLY:
|
||||
case TOK_RESET_ADDR:
|
||||
case TOK_ALIAS_REV:
|
||||
@ -821,6 +826,9 @@ ipfw_config_nat(int ac, char **av)
|
||||
case TOK_UNREG_ONLY:
|
||||
n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
|
||||
break;
|
||||
case TOK_SKIP_GLOBAL:
|
||||
n->mode |= PKT_ALIAS_SKIP_GLOBAL;
|
||||
break;
|
||||
case TOK_RESET_ADDR:
|
||||
n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
|
||||
break;
|
||||
|
@ -2194,6 +2194,13 @@ do { \
|
||||
int nat_id;
|
||||
|
||||
set_match(args, f_pos, chain);
|
||||
/* Check if this is 'global' nat rule */
|
||||
if (cmd->arg1 == 0) {
|
||||
retval = ipfw_nat_ptr(args, NULL, m);
|
||||
l = 0;
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
t = ((ipfw_insn_nat *)cmd)->nat;
|
||||
if (t == NULL) {
|
||||
nat_id = (cmd->arg1 == IP_FW_TABLEARG) ?
|
||||
|
@ -207,7 +207,8 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
|
||||
struct mbuf *mcl;
|
||||
struct ip *ip;
|
||||
/* XXX - libalias duct tape */
|
||||
int ldt, retval;
|
||||
int ldt, retval, found;
|
||||
struct ip_fw_chain *chain;
|
||||
char *c;
|
||||
|
||||
ldt = 0;
|
||||
@ -256,12 +257,44 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
|
||||
ldt = 1;
|
||||
|
||||
c = mtod(mcl, char *);
|
||||
if (args->oif == NULL)
|
||||
retval = LibAliasIn(t->lib, c,
|
||||
mcl->m_len + M_TRAILINGSPACE(mcl));
|
||||
else
|
||||
retval = LibAliasOut(t->lib, c,
|
||||
mcl->m_len + M_TRAILINGSPACE(mcl));
|
||||
|
||||
/* Check if this is 'global' instance */
|
||||
if (t == NULL) {
|
||||
if (args->oif == NULL) {
|
||||
/* Wrong direction, skip processing */
|
||||
args->m = mcl;
|
||||
return (IP_FW_NAT);
|
||||
}
|
||||
|
||||
found = 0;
|
||||
chain = &V_layer3_chain;
|
||||
IPFW_RLOCK(chain);
|
||||
/* Check every nat entry... */
|
||||
LIST_FOREACH(t, &chain->nat, _next) {
|
||||
if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0)
|
||||
continue;
|
||||
retval = LibAliasOutTry(t->lib, c,
|
||||
mcl->m_len + M_TRAILINGSPACE(mcl), 0);
|
||||
if (retval == PKT_ALIAS_OK) {
|
||||
/* Nat instance recognises state */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
IPFW_RUNLOCK(chain);
|
||||
if (found != 1) {
|
||||
/* No instance found, return ignore */
|
||||
args->m = mcl;
|
||||
return (IP_FW_NAT);
|
||||
}
|
||||
} else {
|
||||
if (args->oif == NULL)
|
||||
retval = LibAliasIn(t->lib, c,
|
||||
mcl->m_len + M_TRAILINGSPACE(mcl));
|
||||
else
|
||||
retval = LibAliasOut(t->lib, c,
|
||||
mcl->m_len + M_TRAILINGSPACE(mcl));
|
||||
}
|
||||
|
||||
/*
|
||||
* We drop packet when:
|
||||
@ -274,7 +307,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
|
||||
if (retval == PKT_ALIAS_ERROR ||
|
||||
(args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
|
||||
(retval == PKT_ALIAS_IGNORED &&
|
||||
(t->lib->packetAliasMode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
|
||||
(t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
|
||||
/* XXX - should i add some logging? */
|
||||
m_free(mcl);
|
||||
args->m = NULL;
|
||||
|
@ -220,6 +220,12 @@ struct mbuf *m_megapullup(struct mbuf *, int);
|
||||
#define PKT_ALIAS_PUNCH_FW 0x100
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching
|
||||
* states in 'ipfw nat global' rule.
|
||||
*/
|
||||
#define PKT_ALIAS_SKIP_GLOBAL 0x200
|
||||
|
||||
/* Function return codes. */
|
||||
#define PKT_ALIAS_ERROR -1
|
||||
#define PKT_ALIAS_OK 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user