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;

Attachment: pgpU8AfaVsqmb.pgp
Description: PGP signature

Reply via email to