patchpanel: apply VPN routing tag
This patch adds to patchpanel datapath service the iptables rules for:
- Tagging with the VPN routing tag 0xfffe0000 the fwmark of all
packets that should be routed through a VPN.
- Saving in conntrack the VPN routing tag of all traffic routed through
a VPN.
- Restoring the routing tag (VPN or physical) of any established
connection for sockets in the host namespaces.
This patch together with the shill ip rule patch with Change-Id
I534337bc6cad8b16a723c38cf9bb5d71f89bd831 effectively migrates the VPN
routing implementation from being based fully routing rules and uid
matching to being based on the new fwmark routing tags managed by
patchpanel.
BUG=b:161507671
BUG=chromium:1022028
BUG=chromium:911954
BUG=chromium:973065
TEST=Flashed rammus with patchpanel routing changes, connected multiple
types of VPNs:
- l2tp full tunnel without Internet,
- OpenVPN split tunnel,
- Android VPNs full tunnel,
- Chrome AnyConnect split tunnel,
and conducted various testing:
- General connectivity using ping, traceroute, wget (or equivalent
actions) on Chrome, Linux VM terminal, ARC, crosh, shell.
- Checked DNS settings and DNS reachability.
- Checked Internet reachability for VPNs with Internet.
- Checked split routing for VPNs with split routing setup.
- Checked connection pinning for Chrome, Linux VMs, ARC, shell.
Cq-Depend: chromium:2532025
Disallow-Recycled-Builds: hatch-cq
Change-Id: I2f342faac4b662610be024d62e7c18d04cddfb09
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2499121
Tested-by: Hugo Benichi <hugobenichi@google.com>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Reviewed-by: Garrick Evans <garrick@chromium.org>
diff --git a/patchpanel/datapath_test.cc b/patchpanel/datapath_test.cc
index 0ec69e3..005e278 100644
--- a/patchpanel/datapath_test.cc
+++ b/patchpanel/datapath_test.cc
@@ -183,6 +183,17 @@
ElementsAre("-A", "PREROUTING", "-i", "vmtap+", "-j",
"MARK", "--set-mark", "1/1", "-w"),
true, nullptr));
+ // Asserts for OUTPUT CONNMARK restore rule
+ EXPECT_CALL(runner, iptables(StrEq("mangle"),
+ ElementsAre("-A", "OUTPUT", "-j", "CONNMARK",
+ "--restore-mark", "--mask",
+ "0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-A", "OUTPUT", "-j", "CONNMARK",
+ "--restore-mark", "--mask",
+ "0xffff0000", "-w"),
+ true, nullptr));
// Asserts for apply_local_source_mark chain
EXPECT_CALL(runner,
iptables(StrEq("mangle"),
@@ -444,6 +455,17 @@
ElementsAre("-D", "OUTPUT", "-j",
"apply_local_source_mark", "-w"),
true, nullptr));
+ // Asserts for OUTPUT CONNMARK restore rule
+ EXPECT_CALL(runner, iptables(StrEq("mangle"),
+ ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
+ "--restore-mark", "--mask",
+ "0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
+ "--restore-mark", "--mask",
+ "0xffff0000", "-w"),
+ true, nullptr));
EXPECT_CALL(runner,
iptables(StrEq("mangle"),
ElementsAre("-F", "apply_local_source_mark", "-w"), true,
@@ -1091,6 +1113,59 @@
datapath.StopConnectionPinning("eth0");
}
+TEST(DatapathTest, StartStopVpnRouting_NoVirtualDevices) {
+ MockProcessRunner runner;
+ MockFirewall firewall;
+
+ // Setup
+ EXPECT_CALL(runner, iptables(StrEq("mangle"),
+ ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
+ "-j", "CONNMARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner,
+ iptables(StrEq("mangle"),
+ ElementsAre("-A", "apply_vpn_mark", "-j", "MARK",
+ "--set-mark", "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
+ "-j", "CONNMARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-A", "apply_vpn_mark", "-j",
+ "MARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ // Teardown
+ EXPECT_CALL(runner, iptables(StrEq("mangle"),
+ ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
+ "-j", "CONNMARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner,
+ iptables(StrEq("mangle"),
+ ElementsAre("-D", "apply_vpn_mark", "-j", "MARK",
+ "--set-mark", "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
+ "-j", "CONNMARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+ EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+ ElementsAre("-D", "apply_vpn_mark", "-j",
+ "MARK", "--set-mark",
+ "0x03ed0000/0xffff0000", "-w"),
+ true, nullptr));
+
+ Datapath datapath(&runner, &firewall);
+ datapath.SetIfnameIndex("arcbr0", 5);
+ datapath.StartVpnRouting("arcbr0");
+ datapath.StopVpnRouting("arcbr0");
+}
+
TEST(DatapathTest, AddInboundIPv4DNAT) {
MockProcessRunner runner;
MockFirewall firewall;