On 25.07.2017 10:36, Muenz, Michael wrote:
> Am 24.07.2017 um 19:01 schrieb Andrey V. Elsukov:
>>
>> .1.1: ICMP echo reply, id 33347, seq 28416, length 8
>> This does not match with what I expected to see. The reply here should
>> be something like "10.24.66.25 > 10.26.2.N: ICMP echo reply".
>>
>> It seems the problem is with ipfw_nat, that for both directions thinks
>> that packets are inbound and this leads to incorrect translation.
>>
>> Can you modify your IPsec security policies, so outgoing packets from
>> 10.26.2.0/24 will go through the same tunnel? Then you need to modify
>> nat rule:
>>
>> ipfw nat 1 config ip 10.26.1.1
>> ipfw add 179 nat 1 log ip from 10.26.2.0/24 to 10.24.66.0/24 out xmit
>> enc0
>> ipfw add 179 nat 1 log ip from 10.24.66.0/24 to 10.26.1.1 in recv enc0
>>
> 
> Hi,
> 
> when I change it to
> 
> out xmit enc0
> 
> nothing happens because the packets have to math the IPSEC SA before
> entering the tunnel (and enc0 I guess).
> So it has to be
> 
> in recv vtnet1

ICMP request should be matched by outbound IPsec policy. Looking to your
tcpdump, you use tunnel IPsec mode. So, how this should work:

* 10.26.2.N sends ICMP request to 10.24.66.25

* 10.26.1.1 handles it by tunnel mode IPsec security policy, something like:
        spdadd -4 10.26.2.0/24 10.24.66.0/24 any -P out ipsec \
            esp/tunnel/213.244.192.191-81.24.74.3/require;
* IPsec code does lookup for IPsec SA and uses something like:
        add 213.244.192.191 81.24.74.3 esp 0x2478d746 -m tunnel -E ...;

* Then if_enc(4) pfil handler is called and now you need to do address
translation (with net.enc.out.ipsec_filter_mask=1), and in tcpdump you
should see not yet translated packet:
        10.26.2.N > 10.24.66.25: ICMP echo request ....

* Then IPsec code does IP encapsulation and you will see:
        213.244.192.191 > 81.24.74.3: IPIP ...
            10.26.1.1 > 10.24.66.25: ICMP echo request

(in my previous patch was a bug, and you did not see outbound packet two
times in tcpdump, I attached new patch where it is fixed)

* Then IPsec sends encrypted packet to 81.24.74.3.

* The second host sends ICMP reply to 10.26.1.1.

* 213.244.192.191 recieves encrypted packet and does IPsec SA lookup, it
should have something like:
        add 81.24.74.3 213.244.192.191 esp 0xce702ac1 -m tunnel -E ...;

* IPsec code does decryption and if_enc(4) hook  is called, and you will
see in the tcpdump:
        81.24.74.3 > 213.244.192.191: IPIP ...
            10.24.66.25 > 10.26.1.1: ICMP echo reply

* Since we use net.enc.out.ipsec_filter_mask=2, this packet will not be
handled by firewall and IPsec will do IP decapsultion, and then will
pass decapsulated packet to the pfil where it will be translated:
        10.24.66.25 > 10.26.2.N: ICMP echo reply ....

* Then this packet goes to ip_input() -> ip_forward() processing. To
avoid extra IPsec processing you should have no security policy that
matches "10.24.66.25 > 10.26.2.N" packet, or this should be policy that
requires "none" IPsec processing.

* Then ip_forward() sends this packet to 10.26.2.N.

-- 
WBR, Andrey V. Elsukov
Index: sys/net/if_enc.c
===================================================================
--- sys/net/if_enc.c	(revision 321414)
+++ sys/net/if_enc.c	(working copy)
@@ -223,10 +223,11 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, vo
 	if (ctx->af != hhook_id)
 		return (EPFNOSUPPORT);
 
-	if (((hhook_type == HHOOK_TYPE_IPSEC_IN &&
-	    (ctx->enc & V_bpf_mask_in) != 0) ||
+	if ((ctx->enc & IPSEC_ENC_BEFORE) != 0 && (
+	    (hhook_type == HHOOK_TYPE_IPSEC_IN &&
+	    (V_bpf_mask_in & IPSEC_ENC_BEFORE) != 0) ||
 	    (hhook_type == HHOOK_TYPE_IPSEC_OUT &&
-	    (ctx->enc & V_bpf_mask_out) != 0)) &&
+	    (V_bpf_mask_out & IPSEC_ENC_BEFORE) != 0)) &&
 	    bpf_peers_present(ifp->if_bpf) != 0) {
 		hdr.af = ctx->af;
 		hdr.spi = ctx->sav->spi;
@@ -247,7 +248,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, vo
 			    (*ctx->mp)->m_pkthdr.len);
 		}
 		if ((ctx->enc & V_filter_mask_in) == 0)
-			return (0); /* skip pfil processing */
+			goto handle_bpf; /* skip pfil processing */
 		pdir = PFIL_IN;
 		break;
 	case HHOOK_TYPE_IPSEC_OUT:
@@ -258,7 +259,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, vo
 			    (*ctx->mp)->m_pkthdr.len);
 		}
 		if ((ctx->enc & V_filter_mask_out) == 0)
-			return (0); /* skip pfil processing */
+			goto handle_bpf; /* skip pfil processing */
 		pdir = PFIL_OUT;
 		break;
 	default:
@@ -280,7 +281,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, vo
 		ph = NULL;
 	}
 	if (ph == NULL || !PFIL_HOOKED(ph))
-		return (0);
+		goto handle_bpf;
 	/* Make a packet looks like it was received on enc(4) */
 	rcvif = (*ctx->mp)->m_pkthdr.rcvif;
 	(*ctx->mp)->m_pkthdr.rcvif = ifp;
@@ -290,6 +291,24 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, vo
 		return (EACCES);
 	}
 	(*ctx->mp)->m_pkthdr.rcvif = rcvif;
+
+handle_bpf:
+	if ((ctx->enc & IPSEC_ENC_AFTER) != 0 && (
+	    (hhook_type == HHOOK_TYPE_IPSEC_IN &&
+	    (V_bpf_mask_in & IPSEC_ENC_AFTER) != 0) ||
+	    (hhook_type == HHOOK_TYPE_IPSEC_OUT &&
+	    (V_bpf_mask_out & IPSEC_ENC_AFTER) != 0)) &&
+	    bpf_peers_present(ifp->if_bpf) != 0) {
+		hdr.af = ctx->af;
+		hdr.spi = ctx->sav->spi;
+		hdr.flags = 0;
+		if (ctx->sav->alg_enc != SADB_EALG_NONE)
+			hdr.flags |= M_CONF;
+		if (ctx->sav->alg_auth != SADB_AALG_NONE)
+			hdr.flags |= M_AUTH;
+		bpf_mtap2(ifp->if_bpf, &hdr, sizeof(hdr), *ctx->mp);
+	}
+
 	return (0);
 }
 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to