Hello folks, This patch brings nat capabilites into iked, the same way that mpf@ did with isakmpd about 6 years ago.
Comments ?
Tested with the following setup, with icmp, udp and tcp:
>> Local pf.conf:
table <homev4> { 172.23.0.0/23 }
set skip on lo
match out on enc0 from ! <homev4> to <homev4> nat-to 172.23.50.1
block return
pass
block return in on ! lo0 proto tcp to port 6000:6010
>> Local iked.conf:
ikev2 active esp \
from 172.23.50.1 (0.0.0.0/0) to 172.23.0.0/23 peer 79.143.250.153 \
srcid 'spinoza.kilob.yt' dstid 'brouwer.kilob.yt'
>> Local ip address:
ppp0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
priority: 0
groups: ppp egress
inet 100.97.217.112 --> 10.64.64.64 netmask 0xff000000
>> Remote pf.conf:
[...]
pass on enc0
[...]
>> Remote iked.conf:
ikev2 esp \
from 172.23.0.0/23 to 172.23.50.1 peer any \
srcid 'brouwer.kilob.yt' dstid 'spinoza.kilob.yt'
Index: iked.h
===================================================================
RCS file: /cvs/src/sbin/iked/iked.h,v
retrieving revision 1.82
diff -u -p -r1.82 iked.h
--- iked.h 18 Aug 2014 09:43:02 -0000 1.82
+++ iked.h 15 Jan 2015 13:54:46 -0000
@@ -139,6 +139,8 @@ struct iked_flow {
struct iked_addr flow_src;
struct iked_addr flow_dst;
u_int flow_dir; /* in/out */
+ struct iked_addr flow_prenat; /* pre-nat source */
+ u_int flow_usenat;
u_int flow_loaded; /* pfkey done */
Index: parse.y
===================================================================
RCS file: /cvs/src/sbin/iked/parse.y,v
retrieving revision 1.43
diff -u -p -r1.43 parse.y
--- parse.y 12 Jan 2015 11:24:58 -0000 1.43
+++ parse.y 15 Jan 2015 13:54:47 -0000
@@ -2401,7 +2401,7 @@ create_ike(char *name, int af, u_int8_t
{
char idstr[IKED_ID_SIZE];
u_int idtype = IKEV2_ID_NONE;
- struct ipsec_addr_wrap *ipa, *ipb;
+ struct ipsec_addr_wrap *ipa, *ipb, *ipn;
struct iked_policy pol;
struct iked_proposal prop[2];
u_int j;
@@ -2622,6 +2622,16 @@ create_ike(char *name, int af, u_int8_t
flows[j].flow_dst.addr_mask = ipb->mask;
flows[j].flow_dst.addr_net = ipb->netaddress;
flows[j].flow_dst.addr_port = hosts->dport;
+
+ ipn = ipa->srcnat;
+ if (ipn) {
+ memcpy(&flows[j].flow_prenat.addr, &ipn->address,
+ sizeof(ipn->address));
+ flows[j].flow_prenat.addr_af = ipn->af;
+ flows[j].flow_prenat.addr_mask = ipn->mask;
+ flows[j].flow_prenat.addr_net = ipn->netaddress;
+ flows[j].flow_usenat = 1;
+ }
flows[j].flow_ipproto = ipproto;
Index: pfkey.c
===================================================================
RCS file: /cvs/src/sbin/iked/pfkey.c,v
retrieving revision 1.40
diff -u -p -r1.40 pfkey.c
--- pfkey.c 29 Oct 2014 06:26:39 -0000 1.40
+++ pfkey.c 15 Jan 2015 13:54:47 -0000
@@ -180,6 +180,7 @@ int
pfkey_flow(int sd, u_int8_t satype, u_int8_t action, struct iked_flow *flow)
{
struct sadb_msg smsg;
+ struct iked_addr *flow_src, *flow_dst;
struct sadb_address sa_src, sa_dst, sa_local, sa_peer, sa_smask,
sa_dmask;
struct sadb_protocol sa_flowtype, sa_protocol;
@@ -192,58 +193,76 @@ pfkey_flow(int sd, u_int8_t satype, u_in
sport = dport = 0;
sa_srcid = sa_dstid = NULL;
+ flow_src = &flow->flow_src;
+ flow_dst = &flow->flow_dst;
+
+ if (flow->flow_usenat)
+ switch (flow->flow_type) {
+ case SADB_X_FLOW_TYPE_USE:
+ flow_dst = &flow->flow_prenat;
+ break;
+ case SADB_X_FLOW_TYPE_REQUIRE:
+ flow_src = &flow->flow_prenat;
+ break;
+ case 0:
+ if (flow->flow_dir == IPSP_DIRECTION_IN)
+ flow_dst = &flow->flow_prenat;
+ else
+ flow_src = &flow->flow_prenat;
+ }
+
bzero(&ssrc, sizeof(ssrc));
bzero(&smask, sizeof(smask));
- memcpy(&ssrc, &flow->flow_src.addr, sizeof(ssrc));
- memcpy(&smask, &flow->flow_src.addr, sizeof(smask));
- if ((sport = flow->flow_src.addr_port) != 0)
+ memcpy(&ssrc, &flow_src->addr, sizeof(ssrc));
+ memcpy(&smask, &flow_src->addr, sizeof(smask));
+ if ((sport = flow_src->addr_port) != 0)
dport = 0xffff;
socket_af((struct sockaddr *)&ssrc, sport);
socket_af((struct sockaddr *)&smask, dport);
- switch (flow->flow_src.addr_af) {
+ switch (flow_src->addr_af) {
case AF_INET:
((struct sockaddr_in *)&smask)->sin_addr.s_addr =
- prefixlen2mask(flow->flow_src.addr_net ?
- flow->flow_src.addr_mask : 32);
+ prefixlen2mask(flow_src->addr_net ?
+ flow_src->addr_mask : 32);
break;
case AF_INET6:
- prefixlen2mask6(flow->flow_src.addr_net ?
- flow->flow_src.addr_mask : 128,
+ prefixlen2mask6(flow_src->addr_net ?
+ flow_src->addr_mask : 128,
(u_int32_t *)((struct sockaddr_in6 *)
&smask)->sin6_addr.s6_addr);
break;
default:
log_warnx("%s: unsupported address family %d",
- __func__, flow->flow_src.addr_af);
+ __func__, flow_src->addr_af);
return (-1);
}
smask.ss_len = ssrc.ss_len;
bzero(&sdst, sizeof(sdst));
bzero(&dmask, sizeof(dmask));
- memcpy(&sdst, &flow->flow_dst.addr, sizeof(sdst));
- memcpy(&dmask, &flow->flow_dst.addr, sizeof(dmask));
- if ((sport = flow->flow_dst.addr_port) != 0)
+ memcpy(&sdst, &flow_dst->addr, sizeof(sdst));
+ memcpy(&dmask, &flow_dst->addr, sizeof(dmask));
+ if ((sport = flow_dst->addr_port) != 0)
dport = 0xffff;
socket_af((struct sockaddr *)&sdst, sport);
socket_af((struct sockaddr *)&dmask, dport);
- switch (flow->flow_dst.addr_af) {
+ switch (flow_dst->addr_af) {
case AF_INET:
((struct sockaddr_in *)&dmask)->sin_addr.s_addr =
- prefixlen2mask(flow->flow_dst.addr_net ?
- flow->flow_dst.addr_mask : 32);
+ prefixlen2mask(flow_dst->addr_net ?
+ flow_dst->addr_mask : 32);
break;
case AF_INET6:
- prefixlen2mask6(flow->flow_dst.addr_net ?
- flow->flow_dst.addr_mask : 128,
+ prefixlen2mask6(flow_dst->addr_net ?
+ flow_dst->addr_mask : 128,
(u_int32_t *)((struct sockaddr_in6 *)
&dmask)->sin6_addr.s6_addr);
break;
default:
log_warnx("%s: unsupported address family %d",
- __func__, flow->flow_dst.addr_af);
+ __func__, flow_dst->addr_af);
return (-1);
}
dmask.ss_len = sdst.ss_len;
pgpU8AfaVsqmb.pgp
Description: PGP signature
