Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102115381
D23450.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D23450.diff
View Options
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -3271,6 +3271,9 @@
Obey transparent proxy rules only, packet aliasing is not performed.
.It Cm skip_global
Skip instance in case of global state lookup (see below).
+.It Cm port_range Ar lower-upper
+Set the aliasing ports between the ranges given. Upper port has to be greater
+than lower.
.El
.Pp
Some specials value can be supplied instead of
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -285,6 +285,7 @@
TOK_STATES_CHUNKS,
TOK_JMAXLEN,
TOK_PORT_RANGE,
+ TOK_PORT_ALIAS,
TOK_HOST_DEL_AGE,
TOK_PG_DEL_AGE,
TOK_TCP_SYN_AGE,
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -45,7 +45,8 @@
"[pipe|queue] {zero|delete|show} [N{,N}]\n"
"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|\n"
" reset|reverse|proxy_only|redirect_addr linkspec|\n"
-" redirect_port linkspec|redirect_proto linkspec}\n"
+" redirect_port linkspec|redirect_proto linkspec|\n"
+" port_range lower-upper}\n"
"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
"set N {show|list|zero|resetlog|delete} [N{,N}] | flush\n"
"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -65,6 +65,7 @@
{ "reset", TOK_RESET_ADDR },
{ "reverse", TOK_ALIAS_REV },
{ "proxy_only", TOK_PROXY_ONLY },
+ { "port_range", TOK_PORT_ALIAS },
{ "redirect_addr", TOK_REDIR_ADDR },
{ "redirect_port", TOK_REDIR_PORT },
{ "redirect_proto", TOK_REDIR_PROTO },
@@ -753,12 +754,35 @@
printf("\n");
}
+static int
+nat_port_alias_parse(char *str, u_short *lpout, u_short *hpout) {
+ long lp, hp;
+ char *ptr;
+ /* Lower port parsing */
+ lp = (long) strtol(str, &ptr, 10);
+ if (lp < 1024 || lp > 65535)
+ return 0;
+ if (!ptr || *ptr != '-')
+ return 0;
+ /* Upper port parsing */
+ hp = (long) strtol(ptr, &ptr, 10);
+ if (hp < 1024 || hp > 65535)
+ return 0;
+ if (ptr)
+ return 0;
+
+ *lpout = (u_short) lp;
+ *hpout = (u_short) hp;
+ return 1;
+}
+
void
ipfw_config_nat(int ac, char **av)
{
ipfw_obj_header *oh;
struct nat44_cfg_nat *n; /* Nat instance configuration. */
int i, off, tok, ac1;
+ u_short lp, hp;
char *id, *buf, **av1, *end;
size_t len;
@@ -786,6 +810,7 @@
switch (tok) {
case TOK_IP:
case TOK_IF:
+ case TOK_PORT_ALIAS:
ac1--;
av1++;
break;
@@ -925,8 +950,24 @@
n->redir_cnt++;
off += i;
break;
+ case TOK_PORT_ALIAS:
+ if (ac == 0)
+ errx(EX_DATAERR, "missing option");
+ if (!nat_port_alias_parse(av[0], &lp, &hp))
+ errx(EX_DATAERR,
+ "You need a range of port(s) from 1024 <= x < 65536");
+ if (lp >= hp)
+ errx(EX_DATAERR,
+ "Upper port has to be greater than lower port");
+ n->alias_port_lo = lp;
+ n->alias_port_hi = hp;
+ ac--;
+ av++;
+ break;
}
}
+ if (n->mode & PKT_ALIAS_SAME_PORTS && n->alias_port_lo)
+ errx(EX_DATAERR, "same_ports and port_range cannot both be selected");
i = do_set3(IP_FW_NAT44_XCONFIG, &oh->opheader, len);
if (i != 0)
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -549,6 +549,8 @@
struct in_addr ip; /* nat IPv4 address */
uint32_t mode; /* aliasing mode */
uint32_t redir_cnt; /* number of entry in spool chain */
+ u_short alias_port_lo; /* low range for port aliasing */
+ u_short alias_port_hi; /* high range for port aliasing */
};
/* Nat command. */
diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h
--- a/sys/netinet/libalias/alias.h
+++ b/sys/netinet/libalias/alias.h
@@ -86,6 +86,7 @@
/* Initialization and control functions. */
struct libalias *LibAliasInit(struct libalias *);
void LibAliasSetAddress(struct libalias *, struct in_addr _addr);
+void LibAliasSetAliasPortRange(struct libalias *la, u_short port_low, u_short port_hi);
void LibAliasSetFWBase(struct libalias *, unsigned int _base, unsigned int _num);
void LibAliasSetSkinnyPort(struct libalias *, unsigned int _port);
unsigned int
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -595,6 +595,11 @@
*/
port_net = lnk->src_port;
port_sys = ntohs(port_net);
+ } else if (la->aliasPortLower) {
+ /* First trial is a random port in the aliasing range. */
+ port_sys = la->aliasPortLower +
+ (arc4random() % la->aliasPortLength);
+ port_net = htons(port_sys);
} else {
/* First trial and all subsequent are random. */
port_sys = arc4random() & ALIAS_PORT_MASK;
@@ -647,9 +652,15 @@
}
#endif
}
- port_sys = arc4random() & ALIAS_PORT_MASK;
- port_sys += ALIAS_PORT_BASE;
- port_net = htons(port_sys);
+ if (la->aliasPortLower) {
+ port_sys = la->aliasPortLower +
+ (arc4random() % la->aliasPortLength);
+ port_net = htons(port_sys);
+ } else {
+ port_sys = arc4random() & ALIAS_PORT_MASK;
+ port_sys += ALIAS_PORT_BASE;
+ port_net = htons(port_sys);
+ }
}
#ifdef LIBALIAS_DEBUG
@@ -2381,6 +2392,19 @@
LIBALIAS_UNLOCK(la);
}
+
+void
+LibAliasSetAliasPortRange(struct libalias *la, u_short port_low,
+ u_short port_high)
+{
+
+ LIBALIAS_LOCK(la);
+ la->aliasPortLower = port_low;
+ /* Add 1 to the aliasPortLength as modulo has range of 1 to n-1 */
+ la->aliasPortLength = port_high - port_low + 1;
+ LIBALIAS_UNLOCK(la);
+}
+
void
LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
{
diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h
--- a/sys/netinet/libalias/alias_local.h
+++ b/sys/netinet/libalias/alias_local.h
@@ -163,6 +163,10 @@
struct in_addr true_addr; /* in network byte order. */
u_short true_port; /* in host byte order. */
+ /* Port ranges for aliasing. */
+ u_short aliasPortLower;
+ u_short aliasPortLength;
+
/*
* sctp code support
*/
diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c
--- a/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/sys/netpfil/ipfw/ip_fw_nat.c
@@ -93,6 +93,8 @@
/* chain of redir instances */
LIST_HEAD(redir_chain, cfg_redir) redir_chain;
char if_name[IF_NAMESIZE]; /* interface name */
+ u_short alias_port_lo; /* low range for port aliasing */
+ u_short alias_port_hi; /* high range for port aliasing */
};
static eventhandler_tag ifaddr_event_tag;
@@ -528,9 +530,12 @@
ptr->ip = ucfg->ip;
ptr->redir_cnt = ucfg->redir_cnt;
ptr->mode = ucfg->mode;
+ ptr->alias_port_lo = ucfg->alias_port_lo;
+ ptr->alias_port_hi = ucfg->alias_port_hi;
strlcpy(ptr->if_name, ucfg->if_name, sizeof(ptr->if_name));
LibAliasSetMode(ptr->lib, ptr->mode, ~0);
LibAliasSetAddress(ptr->lib, ptr->ip);
+ LibAliasSetAliasPortRange(ptr->lib, ptr->alias_port_lo, ptr->alias_port_hi);
/*
* Redir and LSNAT configuration.
@@ -658,6 +663,8 @@
ucfg->ip = ptr->ip;
ucfg->redir_cnt = ptr->redir_cnt;
ucfg->mode = ptr->mode;
+ ucfg->alias_port_lo = ptr->alias_port_lo;
+ ucfg->alias_port_hi = ptr->alias_port_hi;
strlcpy(ucfg->if_name, ptr->if_name, sizeof(ucfg->if_name));
}
diff --git a/tests/sys/netpfil/common/nat.sh b/tests/sys/netpfil/common/nat.sh
--- a/tests/sys/netpfil/common/nat.sh
+++ b/tests/sys/netpfil/common/nat.sh
@@ -147,10 +147,107 @@
firewall_cleanup $firewall
}
+common_cgn() {
+ firewall=$1
+ portalias=$2
+ firewall_init $firewall
+ nat_init $firewall
+
+ epair_host_nat=$(vnet_mkepair)
+ epair_client1_nat=$(vnet_mkepair)
+ epair_client2_nat=$(vnet_mkepair)
+
+ vnet_mkjail nat ${epair_host_nat}b ${epair_client1_nat}a ${epair_client2_nat}a
+ vnet_mkjail client1 ${epair_client1_nat}b
+ vnet_mkjail client2 ${epair_client2_nat}b
+
+ ifconfig ${epair_host_nat}a 198.51.100.2/24 up
+ jexec nat ifconfig ${epair_host_nat}b 198.51.100.1/24 up
+
+ jexec nat ifconfig ${epair_client1_nat}a 100.64.0.1/24 up
+ jexec client1 ifconfig ${epair_client1_nat}b 100.64.0.2/24 up
+
+ jexec nat ifconfig ${epair_client2_nat}a 100.64.1.1/24 up
+ jexec client2 ifconfig ${epair_client2_nat}b 100.64.1.2/24 up
+
+ jexec nat sysctl net.inet.ip.forwarding=1
+
+ jexec client1 route add -net 198.51.100.0/24 100.64.0.1
+ jexec client2 route add -net 198.51.100.0/24 100.64.1.1
+
+ # ping fails without NAT configuration
+ atf_check -s exit:2 -o ignore jexec client1 ping -t 1 -c 1 198.51.100.2
+ atf_check -s exit:2 -o ignore jexec client2 ping -t 1 -c 1 198.51.100.2
+
+ if [[ $portalias ]]; then
+ firewall_config nat $firewall \
+ "ipfw" \
+ "ipfw -q nat 123 config if ${epair_host_nat}b unreg_cgn port_alias 2000-2999" \
+ "ipfw -q nat 456 config if ${epair_host_nat}b unreg_cgn port_alias 3000-3999" \
+ "ipfw -q add 1000 nat 123 all from any to 198.51.100.2 2000-2999 in via ${epair_host_nat}b" \
+ "ipfw -q add 2000 nat 456 all from any to 198.51.100.2 3000-3999 in via ${epair_host_nat}b" \
+ "ipfw -q add 3000 nat 123 all from 100.64.0.2 to any out via ${epair_host_nat}b" \
+ "ipfw -q add 4000 nat 456 all from 100.64.1.2 to any out via ${epair_host_nat}b"
+ else
+ firewall_config nat $firewall \
+ "ipfw" \
+ "ipfw -q nat 123 config if ${epair_host_nat}b unreg_cgn" \
+ "ipfw -q add 1000 nat 123 all from any to any"
+ fi
+
+ # ping is successful now
+ atf_check -s exit:0 -o ignore jexec client1 ping -t 1 -c 1 198.51.100.2
+ atf_check -s exit:0 -o ignore jexec client2 ping -t 1 -c 1 198.51.100.2
+
+ # if portalias, test a tcp server/client with nc
+ if [[ $portalias ]]; then
+ for inst in 1 2; do
+ daemon nc -p 198.51.100.2 7
+ atf_check -s exit:0 -o ignore jexec client$inst sh -c "echo | nc -N 198.51.100.2 7"
+ done
+ fi
+}
+
+cgn_head()
+{
+ atf_set descr 'IPv4 CGN (RFC 6598) test'
+ atf_set require.user root
+}
+
+cgn_body()
+{
+ common_cgn $1 false
+}
+
+cgn_cleanup()
+{
+ firewall_cleanup ipfw
+}
+
+portalias_head()
+{
+ atf_set descr 'IPv4 CGN (RFC 6598) port aliasing test'
+ atf_set require.user root
+}
+
+portalias_body()
+{
+ common_cgn $1 true
+}
+
+portalias_cleanup()
+{
+ firewall_cleanup ipfw
+}
+
setup_tests \
basic \
pf \
ipfw \
ipfnat \
userspace_nat \
- ipfw
\ No newline at end of file
+ ipfw \
+ cgn \
+ ipfw \
+ portalias \
+ ipfw
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 8, 7:35 PM (21 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14541423
Default Alt Text
D23450.diff (10 KB)
Attached To
Mode
D23450: libalias: Allow setting alias port ranges
Attached
Detach File
Event Timeline
Log In to Comment