Hi Wolfgang,
Thanks for the testcase. Unfortunately, north has no second uplink/interface
to reach east. So the test can't send the traffic yet. Now we can verify
rules and verify "ip x s" mark/mask. Let me see if there is another way to
test to able to send traffic with fwmark. Add another rule or something,
change http to "nc" as a listener on east.
Tuomo, do you have any ideas to fix this test case? simulate two uplink or
fwmark?
I would the patch more generic, where you can configure output mark. Then
the mark is independent of if_id, for advanced routing usecase this would be
better. Could you test the attached patch? I am not sure I got mark
correct, 8 LSB?
in the config
mark-out=3/0xffffff
ip x s # should show the outputmark with mask[1]
src 192.1.2.23 dst 192.1.3.33
proto esp spi 0xSPISPI reqid REQID mode tunnel
replay-window 32 flag af-unspec
output-mark 0x3/0xffffff
aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128
if_id 0x1
[1] iproute2 mask
along the way I noticed iproute2 does not print the output mark's mask.
I have a quick patch for iproute 2 to print it.
https://github.com/antonyantony/iproute2/commit/69d7df795372a4f6737f9133b80120e2727f1ff3
And the updated testcase:
https://github.com/antonyantony/libreswan/tree/xfrmi-outmark/testing/pluto/ikev2-xfrmi-14-fwmark
On Mon, Aug 10, 2020 at 10:41:35AM +0200, Wolfgang Nothdurft wrote:
> Am 30.07.20 um 07:57 schrieb Antony Antony:
>
> > Can you can help create a testcase with fwmark and xfrmi? you are using
> > marks with KLIPS? so it is not really configured in ipsec.conf? I wonder how
> > that would translate one-to-one.
> >
>
> Attached you can find an simplified testcase that corresponds approximately
> to what we do.
>
> In this case marking http traffic, to route it on an other interface.
>
> iptables -t mangle -I OUTPUT -p tcp --dport 80 -j MARK --set-mark 0x1
> ip ru add prio 1 fwmark 0x1 table 1
> ip r add default dev eth0 table 1
>
> This case passes with my example patch when mapping the fwmark to 0x1000000.
>
> Wolfgang
> commit c5468a72eea2316bf246ba521f17e5f833db9395
> Author: Wolfgang <[email protected]>
> Date: Mon Aug 10 04:29:15 2020 -0400
>
> * prototype testcase for conflicting fwmark with xfrmi
>
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/description.txt
> b/testing/pluto/ikev2-xfrmi-14-fwmark/description.txt
> new file mode 100644
> index 0000000000..d68af1b1ca
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/description.txt
> @@ -0,0 +1 @@
> +The default XFRMi FWMARK conflicts with a policy based route.
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/east.console.txt
> b/testing/pluto/ikev2-xfrmi-14-fwmark/east.console.txt
> new file mode 100644
> index 0000000000..89ec07aef6
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/east.console.txt
> @@ -0,0 +1,20 @@
> +/testing/guestbin/swan-prep
> +east #
> + ipsec start
> +Redirecting to: [initsystem]
> +east #
> + /testing/pluto/bin/wait-until-pluto-started
> +east #
> + ipsec auto --add northnet-eastnet
> +002 added IKEv2 connection "northnet-eastnet"
> +east #
> + echo "initdone"
> +initdone
> +east #
> + ipsec whack --trafficstatus
> +006 #2: "northnet-eastnet", type=ESP, add_time=1234567890, inBytes=336,
> outBytes=336, id='@north'
> +east #
> + ../bin/check-for-core.sh
> +east #
> + if [ -f /sbin/ausearch ]; then ausearch -r -m avc -ts recent ; fi
> +
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/east.secrets
> b/testing/pluto/ikev2-xfrmi-14-fwmark/east.secrets
> new file mode 100644
> index 0000000000..7b53b85edb
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/east.secrets
> @@ -0,0 +1 @@
> +@east @north : PSK "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/eastinit.sh
> b/testing/pluto/ikev2-xfrmi-14-fwmark/eastinit.sh
> new file mode 100755
> index 0000000000..6dc310df8f
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/eastinit.sh
> @@ -0,0 +1,5 @@
> +/testing/guestbin/swan-prep
> +ipsec start
> +/testing/pluto/bin/wait-until-pluto-started
> +ipsec auto --add northnet-eastnet
> +echo "initdone"
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/final.sh
> b/testing/pluto/ikev2-xfrmi-14-fwmark/final.sh
> new file mode 100755
> index 0000000000..35dd99a15b
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/final.sh
> @@ -0,0 +1,7 @@
> +ipsec whack --trafficstatus
> +: ==== cut ====
> +ipsec auto --status
> +: ==== tuc ====
> +../bin/check-for-core.sh
> +if [ -f /sbin/ausearch ]; then ausearch -r -m avc -ts recent ; fi
> +: ==== end ====
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/ipsec.conf
> b/testing/pluto/ikev2-xfrmi-14-fwmark/ipsec.conf
> new file mode 100644
> index 0000000000..67cd088c14
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/ipsec.conf
> @@ -0,0 +1,31 @@
> +# /etc/ipsec.conf - Libreswan IPsec configuration file
> +
> +version 2.0
> +
> +config setup
> + logfile=/tmp/pluto.log
> + logtime=no
> + logappend=no
> + plutodebug="all"
> + protostack=netkey
> + dumpdir=/tmp
> +
> +conn %default
> + authby=secret
> + ikev2=insist
> +
> +conn base
> + rightid=@east
> + leftid=@north
> + left=192.1.3.33
> + right=192.1.2.23
> + leftsubnet=192.0.3.0/24
> +
> +conn northnet-eastnet
> + also=base
> + ipsec-interface=no
> +
> +conn north
> + also=base
> + priority=3
> + ipsec-interface=yes
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/nic.console.txt
> b/testing/pluto/ikev2-xfrmi-14-fwmark/nic.console.txt
> new file mode 100644
> index 0000000000..fcd5477274
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/nic.console.txt
> @@ -0,0 +1,7 @@
> +iptables -t nat -F
> +nic #
> + iptables -F
> +nic #
> + echo "initdone"
> +initdone
> +
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/nicinit.sh
> b/testing/pluto/ikev2-xfrmi-14-fwmark/nicinit.sh
> new file mode 100755
> index 0000000000..d48b3f9ad5
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/nicinit.sh
> @@ -0,0 +1,4 @@
> +iptables -t nat -F
> +iptables -F
> +echo "initdone"
> +: ==== end ====
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/north.console.txt
> b/testing/pluto/ikev2-xfrmi-14-fwmark/north.console.txt
> new file mode 100644
> index 0000000000..ecade8b2c4
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/north.console.txt
> @@ -0,0 +1,93 @@
> +/testing/guestbin/swan-prep
> +north #
> + iptables -t mangle -I OUTPUT -p tcp --dport 80 -j MARK --set-mark 0x1
> +north #
> + ip ru add prio 1 fwmark 0x1 table 1
> +north #
> + ip r add default dev eth0 table 1
> +north #
> + # this route from /etc/sysconfig/network-scripts/route-eth1 interfears
> +north #
> + ip route get to 192.0.2.254 | grep eth1 && ip route del 192.0.2.0/24 via
> 192.1.3.254 dev eth1
> +192.0.2.254 via 192.1.3.254 dev eth1 src 192.1.3.33 uid 0
> +RTNETLINK answers: No such process
> +north #
> + # ip link show ipsec1 2>/dev/null && ip link del ipsec1
> +north #
> + echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
> +north #
> + ipsec start
> +Redirecting to: [initsystem]
> +north #
> + /testing/pluto/bin/wait-until-pluto-started
> +north #
> + ipsec auto --add north
> +002 added IKEv2 connection "north"
> +north #
> + echo "initdone"
> +initdone
> +north #
> + ipsec auto --up north
> +1v2 "north" #1: initiating IKEv2 connection
> +1v2 "north" #1: sent IKE_SA_INIT request
> +1v2 "north" #1: sent IKE_AUTH request {auth=IKEv2 cipher=AES_GCM_16_256
> integ=n/a prf=HMAC_SHA2_512 group=MODP2048}
> +002 "north" #2: IKEv2 mode peer ID is ID_FQDN: '@east'
> +003 "north" #1: authenticated using authby=secret
> +002 "north" #2: negotiated connection [192.0.3.0-192.0.3.255:0-65535 0] ->
> [192.1.2.23-192.1.2.23:0-65535 0]
> +004 "north" #2: IPsec SA established tunnel mode {ESP=>0xESPESP <0xESPESP
> xfrm=AES_GCM_16_256-NONE NATOA=none NATD=none DPD=passive}
> +north #
> + # comments bellow are to understand/explore the basics : what is going on
> +north #
> + # ip link add ipsec1 type xfrm xfrmi-id 1 dev eth0
> +north #
> + # ip link set ipsec1 up
> +north #
> + # ip route add 192.0.2.0/24 dev ipsec1 src 192.0.3.254
> +north #
> + # tcpdump -s 0 -n -w /tmp/ipsec1.pcap -i ipsec1 & echo $! > /tmp/tcpdump.pid
> +north #
> + sleep 2
> +north #
> + ping -w 4 -c 4 192.1.2.23
> +PING 192.1.2.23 (192.1.2.23) 56(84) bytes of data.
> +64 bytes from 192.1.2.23: icmp_seq=1 ttl=64 time=0.XXX ms
> +64 bytes from 192.1.2.23: icmp_seq=2 ttl=64 time=0.XXX ms
> +64 bytes from 192.1.2.23: icmp_seq=3 ttl=64 time=0.XXX ms
> +64 bytes from 192.1.2.23: icmp_seq=4 ttl=64 time=0.XXX ms
> +--- 192.1.2.23 ping statistics ---
> +4 packets transmitted, 4 received, 0% packet loss, time XXXX
> +rtt min/avg/max/mdev = 0.XXX/0.XXX/0.XXX/0.XXX ms
> +north #
> + ip -s link show ipsec1
> +X: ipsec1@eth1: <NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN
> + RX: bytes packets errors dropped overrun mcast
> + 336 4 0 0 0 0
> + TX: bytes packets errors dropped carrier collsns
> + 336 4 0 0 0 0
> +north #
> + #kill -9 $(cat /tmp/tcpdump.pid)
> +north #
> + sleep 2
> +north #
> + #cp /tmp/ipsec1.pcap OUTPUT/
> +north #
> + ip rule show
> +0: from all lookup local
> +1: from all fwmark 0x1 lookup 1
> +100: from all to 192.1.2.23 fwmark 0x1000000 lookup 50
> +32766: from all lookup main
> +32767: from all lookup default
> +north #
> + ip route show table 50
> +192.1.2.23 dev eth1 scope link
> +north #
> + echo done
> +done
> +north #
> + ipsec whack --trafficstatus
> +006 #2: "north", type=ESP, add_time=1234567890, inBytes=336, outBytes=336,
> id='@east'
> +north #
> + ../bin/check-for-core.sh
> +north #
> + if [ -f /sbin/ausearch ]; then ausearch -r -m avc -ts recent ; fi
> +
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/north.secrets
> b/testing/pluto/ikev2-xfrmi-14-fwmark/north.secrets
> new file mode 100644
> index 0000000000..7b53b85edb
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/north.secrets
> @@ -0,0 +1 @@
> +@east @north : PSK "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/northinit.sh
> b/testing/pluto/ikev2-xfrmi-14-fwmark/northinit.sh
> new file mode 100755
> index 0000000000..96c6dd3592
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/northinit.sh
> @@ -0,0 +1,12 @@
> +/testing/guestbin/swan-prep
> +iptables -t mangle -I OUTPUT -p tcp --dport 80 -j MARK --set-mark 0x1
> +ip ru add prio 1 fwmark 0x1 table 1
> +ip r add default dev eth0 table 1
> +# this route from /etc/sysconfig/network-scripts/route-eth1 interfears
> +ip route get to 192.0.2.254 | grep eth1 && ip route del 192.0.2.0/24 via
> 192.1.3.254 dev eth1
> +# ip link show ipsec1 2>/dev/null && ip link del ipsec1
> +echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
> +ipsec start
> +/testing/pluto/bin/wait-until-pluto-started
> +ipsec auto --add north
> +echo "initdone"
> diff --git a/testing/pluto/ikev2-xfrmi-14-fwmark/northrun.sh
> b/testing/pluto/ikev2-xfrmi-14-fwmark/northrun.sh
> new file mode 100755
> index 0000000000..caa3888ebb
> --- /dev/null
> +++ b/testing/pluto/ikev2-xfrmi-14-fwmark/northrun.sh
> @@ -0,0 +1,15 @@
> +ipsec auto --up north
> +# comments bellow are to understand/explore the basics : what is going on
> +# ip link add ipsec1 type xfrm xfrmi-id 1 dev eth0
> +# ip link set ipsec1 up
> +# ip route add 192.0.2.0/24 dev ipsec1 src 192.0.3.254
> +# tcpdump -s 0 -n -w /tmp/ipsec1.pcap -i ipsec1 & echo $! > /tmp/tcpdump.pid
> +sleep 2
> +ping -w 4 -c 4 192.1.2.23
> +ip -s link show ipsec1
> +#kill -9 $(cat /tmp/tcpdump.pid)
> +sleep 2
> +#cp /tmp/ipsec1.pcap OUTPUT/
> +ip rule show
> +ip route show table 50
> +echo done
>From db40495a9713bdef96d5db0feaa75bee59502e2a Mon Sep 17 00:00:00 2001
From: Antony Antony <[email protected]>
Date: Mon, 10 Aug 2020 19:50:07 +0000
Subject: [PATCH 1/2] pluto: xfrmi add configuratio mark
mark-out=<mark>/<mask>
---
programs/pluto/kernel.c | 17 +++++++----
programs/pluto/kernel.h | 1 +
programs/pluto/kernel_xfrm.c | 56 +++++++++++++++++++++++++++---------
3 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/programs/pluto/kernel.c b/programs/pluto/kernel.c
index 07bb2740d6..560501c708 100644
--- a/programs/pluto/kernel.c
+++ b/programs/pluto/kernel.c
@@ -565,14 +565,18 @@ static void jam_common_shell_out(struct jambuf *buf,
const struct connection *c,
jam(buf, "CONNMARK_IN=%" PRIu32 "/%#08" PRIx32 " ",
c->sa_marks.in.val, c->sa_marks.in.mask);
}
- if (c->sa_marks.out.val != 0) {
+ if (c->sa_marks.out.val != 0 && c->xfrmi == NULL) {
jam(buf, "CONNMARK_OUT=%" PRIu32 "/%#08" PRIx32 " ",
c->sa_marks.out.val, c->sa_marks.out.mask);
}
- if (c->xfrmi != NULL && c->xfrmi->if_id > 0) {
- if (addrinsubnet(&sr->that.host_addr, &sr->that.client)) {
+ if (c->xfrmi != NULL) {
+ if (c->sa_marks.out.val != 0) {
+ /* user configured XFRMI_SET_MARK (a.k.a. output mark)
add it */
+ jam(buf, "PLUTO_XFRMI_FWMARK='%" PRIu32 "/%#08" PRIx32
"' ",
+ c->sa_marks.out.val, c->sa_marks.out.mask);
+ } else if (addrinsubnet(&sr->that.host_addr, &sr->that.client))
{
jam(buf, "PLUTO_XFRMI_FWMARK='%" PRIu32 "/0xffffffff' ",
- c->xfrmi->if_id);
+ c->xfrmi->if_id);
} else {
address_buf bpeer;
subnet_buf peerclient_str;
@@ -1940,8 +1944,11 @@ static bool setup_half_ipsec_sa(struct state *st, bool
inbound)
said_next->replay_window = c->sa_replay_window;
dbg("setting IPsec SA replay-window to %d",
c->sa_replay_window);
- if (c->xfrmi != NULL)
+ if (c->xfrmi != NULL) {
said_next->xfrm_if_id = c->xfrmi->if_id;
+ if (c->sa_marks.out.val != 0 || c->sa_marks.out.mask !=
0)
+ said_next->mark_set = c->sa_marks.out;
+ }
if (!inbound && c->sa_tfcpad != 0 && !st->st_seen_no_tfc) {
dbg("Enabling TFC at %d bytes (up to PMTU)",
c->sa_tfcpad);
diff --git a/programs/pluto/kernel.h b/programs/pluto/kernel.h
index 659e306f73..e63de76dde 100644
--- a/programs/pluto/kernel.h
+++ b/programs/pluto/kernel.h
@@ -172,6 +172,7 @@ struct kernel_sa {
struct xfrm_user_sec_ctx_ike *sec_ctx;
const char *nic_offload_dev;
uint32_t xfrm_if_id;
+ struct sa_mark mark_set; /* config keyword mark-out */
deltatime_t sa_lifetime; /* number of seconds until SA expires */
};
diff --git a/programs/pluto/kernel_xfrm.c b/programs/pluto/kernel_xfrm.c
index cecfe8c535..641b89cd56 100644
--- a/programs/pluto/kernel_xfrm.c
+++ b/programs/pluto/kernel_xfrm.c
@@ -723,7 +723,7 @@ static bool netlink_raw_eroute(const ip_address *this_host,
{
struct sa_mark sa_mark = (dir == XFRM_POLICY_IN) ?
sa_marks->in : sa_marks->out;
- if (sa_mark.val != 0 && sa_mark.mask != 0) {
+ if (sa_mark.val != 0 && sa_mark.mask != 0 && xfrm_if_id
== 0) {
struct xfrm_mark xfrm_mark;
struct rtattr* mark_attr;
@@ -747,12 +747,27 @@ static bool netlink_raw_eroute(const ip_address
*this_host,
memcpy(RTA_DATA(attr), &xfrm_if_id, sizeof(uint32_t));
req.n.nlmsg_len += attr->rta_len;
- /* XFRMA_SET_MARK = XFRMA_IF_ID/0xffffffff */
- attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
- attr->rta_type = XFRMA_SET_MARK;
- attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
- memcpy(RTA_DATA(attr), &xfrm_if_id, sizeof(uint32_t));
- req.n.nlmsg_len += attr->rta_len;
+ if (sa_marks->out.val == 0 && sa_marks->out.mask == 0) {
+ /* XFRMA_SET_MARK = XFRMA_IF_ID/0xffffffff */
+ attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
+ attr->rta_type = XFRMA_SET_MARK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &xfrm_if_id,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+ } else {
+ /* mark-out=mark/mask is configured manually */
+ attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
+ attr->rta_type = XFRMA_SET_MARK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &sa_marks->out.val,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+
+ attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
+ attr->rta_type = XFRMA_SET_MARK_MASK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &sa_marks->out.mask,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+ }
#endif
}
@@ -1561,12 +1576,27 @@ static bool netlink_add_sa(const struct kernel_sa *sa,
bool replace)
req.n.nlmsg_len += attr->rta_len;
attr = (struct rtattr *)((char *)attr + attr->rta_len);
- /* XFRMA_SET_MARK = XFRMA_IF_ID/0xffffffff */
- attr->rta_type = XFRMA_SET_MARK;
- attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
- memcpy(RTA_DATA(attr), &sa->xfrm_if_id, sizeof(uint32_t));
- req.n.nlmsg_len += attr->rta_len;
- attr = (struct rtattr *)((char *)attr + attr->rta_len);
+ if (sa->mark_set.val != 0 || sa->mark_set.mask != 0) {
+ /* mark-out=mark/mask is configured manually */
+ attr->rta_type = XFRMA_SET_MARK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &sa->mark_set.val,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
+
+ attr->rta_type = XFRMA_SET_MARK_MASK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &sa->mark_set.mask,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)&req +
req.n.nlmsg_len);
+ } else {
+ /* XFRMA_SET_MARK = XFRMA_IF_ID/0xffffffff */
+ attr->rta_type = XFRMA_SET_MARK;
+ attr->rta_len = RTA_LENGTH(sizeof(uint32_t));
+ memcpy(RTA_DATA(attr), &sa->xfrm_if_id,
sizeof(uint32_t));
+ req.n.nlmsg_len += attr->rta_len;
+ attr = (struct rtattr *)((char *)attr + attr->rta_len);
+ }
#endif
}
--
2.21.3
_______________________________________________
Swan mailing list
[email protected]
https://lists.libreswan.org/mailman/listinfo/swan