From ca41026c892c51326009a357b5b333c4cabcbeae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vieira?= Date: Sun, 28 Oct 2018 19:56:12 +0000 Subject: [PATCH] Changes pf exclusion rules precedence Before this change, in pf, exclusions used a pass out quick which gave them higher precedence than any other rule independent of subnet width. As reported in #265 this causes exclusion from one instance of sshuttle to also take effect on other instances because quick aborts the evaluation of rules across all anchors. This commit changes the precedence of rules so quick can now be dropped. The new order is defined by the following rule, from subnet_weight: "We need to go from smaller, more specific, port ranges, to larger, less-specific, port ranges. At each level, we order by subnet width, from most-specific subnets (largest swidth) to least-specific. On ties, excludes come first." --- sshuttle/methods/pf.py | 6 +++--- tests/client/test_methods_pf.py | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sshuttle/methods/pf.py b/sshuttle/methods/pf.py index d80678f..a8c0d17 100644 --- a/sshuttle/methods/pf.py +++ b/sshuttle/methods/pf.py @@ -217,7 +217,7 @@ class FreeBsd(Generic): b'pass out route-to lo0 %s proto tcp ' b'to %s keep state' % (inet_version, subnet) if not exclude else - b'pass out quick %s proto tcp to %s' % (inet_version, subnet) + b'pass out %s proto tcp to %s' % (inet_version, subnet) for exclude, subnet in includes ] @@ -287,7 +287,7 @@ class OpenBsd(Generic): b'pass out %s proto tcp to %s ' b'route-to lo0 keep state' % (inet_version, subnet) if not exclude else - b'pass out quick %s proto tcp to %s' % (inet_version, subnet) + b'pass out %s proto tcp to %s' % (inet_version, subnet) for exclude, subnet in includes ] @@ -452,7 +452,7 @@ class Method(BaseMethod): # exclusion first; the table will ignore the second, opposite # definition for _, swidth, sexclude, snet, fport, lport \ - in sorted(subnets, key=subnet_weight, reverse=True): + in sorted(subnets, key=subnet_weight): includes.append((sexclude, b"%s/%d%s" % ( snet.encode("ASCII"), swidth, diff --git a/tests/client/test_methods_pf.py b/tests/client/test_methods_pf.py index ebe527f..5375d11 100644 --- a/tests/client/test_methods_pf.py +++ b/tests/client/test_methods_pf.py @@ -205,10 +205,10 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl): b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n' b'rdr pass on lo0 inet6 proto udp ' b'to port 53 -> ::1 port 1026\n' - b'pass out quick inet6 proto tcp to ' - b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out route-to lo0 inet6 proto tcp to ' b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n' + b'pass out inet6 proto tcp to ' + b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out route-to lo0 inet6 proto udp ' b'to port 53 keep state\n'), call('-E'), @@ -257,8 +257,8 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl): b'-> 127.0.0.1 port 1025\n' b'rdr pass on lo0 inet proto udp ' b'to port 53 -> 127.0.0.1 port 1027\n' - b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n' + b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out route-to lo0 inet proto udp ' b'to port 53 keep state\n'), call('-E'), @@ -308,10 +308,10 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl, b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n' b'rdr pass on lo0 inet6 proto udp ' b'to port 53 -> ::1 port 1026\n' - b'pass out quick inet6 proto tcp to ' - b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out route-to lo0 inet6 proto tcp to ' b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n' + b'pass out inet6 proto tcp to ' + b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out route-to lo0 inet6 proto udp ' b'to port 53 keep state\n'), call('-e'), @@ -359,8 +359,8 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl, b'to 1.2.3.0/24 -> 127.0.0.1 port 1025\n' b'rdr pass on lo0 inet proto udp ' b'to port 53 -> 127.0.0.1 port 1027\n' - b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n' + b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out route-to lo0 inet proto udp ' b'to port 53 keep state\n'), call('-e'), @@ -416,10 +416,10 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl): b'port 8000:9000 divert-to ::1 port 1024\n' b'pass in on lo0 inet6 proto udp ' b'to port 53 rdr-to ::1 port 1026\n' - b'pass out quick inet6 proto tcp to ' - b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out inet6 proto tcp to 2404:6800:4004:80c::/64 ' b'port 8000:9000 route-to lo0 keep state\n' + b'pass out inet6 proto tcp to ' + b'2404:6800:4004:80c::101f/128 port 8080:8080\n' b'pass out inet6 proto udp to ' b' port 53 route-to lo0 keep state\n'), call('-e'), @@ -464,8 +464,8 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl): b'127.0.0.1 port 1025\n' b'pass in on lo0 inet proto udp to ' b' port 53 rdr-to 127.0.0.1 port 1027\n' - b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out inet proto tcp to 1.2.3.0/24 route-to lo0 keep state\n' + b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n' b'pass out inet proto udp to ' b' port 53 route-to lo0 keep state\n'), call('-e'),