Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/netpfil/pf/rdr.sh
Show All 21 Lines | |||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
# SUCH DAMAGE. | # SUCH DAMAGE. | ||||
. $(atf_get_srcdir)/utils.subr | . $(atf_get_srcdir)/utils.subr | ||||
atf_test_case "tcp_v6" "cleanup" | |||||
tcp_v6_head() | |||||
{ | |||||
atf_set descr 'TCP rdr with IPv6' | |||||
atf_set require.user root | |||||
atf_set require.progs python3 | |||||
} | |||||
# | # | ||||
# Test that rdr works for TCP with IPv6. | # Test that rdr works for TCP with IPv6. | ||||
# | # | ||||
# a <-----> b <-----> c | # a <-----> b <-----> c | ||||
# | # | ||||
# Test configures three jails (a, b and c) and connects them together with b as | # Test configures three jails (a, b and c) and connects them together with b as | ||||
# a router between a and c. | # a router between a and c. | ||||
# | # | ||||
# TCP traffic to b on port 80 is redirected to c on port 8000 | # TCP traffic to b on port 80 is redirected to c on port 8000 | ||||
# | # | ||||
# Test for incorrect checksums after the rewrite by looking at a packet capture (see bug 210860) | # Test for incorrect checksums after the rewrite by looking at a packet capture (see bug 210860) | ||||
# | # | ||||
tcp_v6_body() | tcp_v6_setup() | ||||
{ | { | ||||
pft_init | pft_init | ||||
j="rdr:tcp_v6" | j="rdr:tcp_v6" | ||||
epair_one=$(vnet_mkepair) | epair_one=$(vnet_mkepair) | ||||
epair_two=$(vnet_mkepair) | epair_two=$(vnet_mkepair) | ||||
echo $epair_one | echo $epair_one | ||||
Show All 19 Lines | tcp_v6_setup() | ||||
# enable forwarding in the b jail | # enable forwarding in the b jail | ||||
jexec ${j}b sysctl net.inet6.ip6.forwarding=1 | jexec ${j}b sysctl net.inet6.ip6.forwarding=1 | ||||
# add routes so a and c can find each other | # add routes so a and c can find each other | ||||
jexec ${j}a route add -inet6 2001:db8:b::0/64 2001:db8:a::1 | jexec ${j}a route add -inet6 2001:db8:b::0/64 2001:db8:a::1 | ||||
jexec ${j}c route add -inet6 2001:db8:a::0/64 2001:db8:b::1 | jexec ${j}c route add -inet6 2001:db8:a::0/64 2001:db8:b::1 | ||||
jexec ${j}b pfctl -e | jexec ${j}b pfctl -e | ||||
} | |||||
pft_set_rules ${j}b \ | tcp_v6_common() | ||||
"rdr on ${epair_one}a proto tcp from any to any port 80 -> 2001:db8:b::2 port 8000" | { | ||||
pft_set_rules ${j}b "${1}" | |||||
# Check that a can reach c over the router | # Check that a can reach c over the router | ||||
atf_check -s exit:0 -o ignore \ | atf_check -s exit:0 -o ignore \ | ||||
jexec ${j}a ping -6 -c 1 2001:db8:b::2 | jexec ${j}a ping -6 -c 1 2001:db8:b::2 | ||||
# capture packets on c so we can look for incorrect checksums | # capture packets on c so we can look for incorrect checksums | ||||
jexec ${j}c tcpdump --immediate-mode -w ${PWD}/${j}.pcap tcp and port 8000 & | jexec ${j}c tcpdump --immediate-mode -w ${PWD}/${j}.pcap tcp and port 8000 & | ||||
tcpdumppid=$! | tcpdumppid=$! | ||||
Show All 14 Lines | tcp_v6_common() | ||||
jexec ${j}c kill -s SIGINT $tcpdumppid | jexec ${j}c kill -s SIGINT $tcpdumppid | ||||
# Check for 'incorrect' in packet capture, this should tell us if | # Check for 'incorrect' in packet capture, this should tell us if | ||||
# checksums are bad with rdr rules | # checksums are bad with rdr rules | ||||
count=$(jexec ${j}c tcpdump -vvvv -r ${PWD}/${j}.pcap | grep incorrect | wc -l) | count=$(jexec ${j}c tcpdump -vvvv -r ${PWD}/${j}.pcap | grep incorrect | wc -l) | ||||
atf_check_equal " 0" "$count" | atf_check_equal " 0" "$count" | ||||
} | } | ||||
tcp_v6_cleanup() | atf_test_case "tcp_v6_compat" "cleanup" | ||||
tcp_v6_compat_head() | |||||
{ | { | ||||
pft_cleanup | atf_set descr 'TCP rdr with IPv6 with NAT rules' | ||||
atf_set require.user root | |||||
atf_set require.progs python3 | |||||
} | } | ||||
tcp_v6_compat_body() | |||||
{ | |||||
tcp_v6_setup # Sets ${epair_…} variables | |||||
tcp_v6_common \ | |||||
"rdr on ${epair_one}a proto tcp from any to any port 80 -> 2001:db8:b::2 port 8000" | |||||
} | |||||
atf_test_case "srcport" "cleanup" | tcp_v6_compat_cleanup() | ||||
srcport_head() | |||||
{ | { | ||||
atf_set descr 'TCP rdr srcport modulation' | pft_cleanup | ||||
} | |||||
atf_test_case "tcp_v6_pass" "cleanup" | |||||
tcp_v6_pass_head() | |||||
{ | |||||
atf_set descr 'TCP rdr with IPv6 with pass/match rules' | |||||
atf_set require.user root | atf_set require.user root | ||||
atf_set require.progs python3 | atf_set require.progs python3 | ||||
atf_set timeout 9999 | |||||
} | } | ||||
tcp_v6_pass_body() | |||||
{ | |||||
tcp_v6_setup # Sets ${epair_…} variables | |||||
tcp_v6_common \ | |||||
"rdr on ${epair_one}a proto tcp from any to any port 80 -> 2001:db8:b::2 port 8000" | |||||
} | |||||
tcp_v6_pass_cleanup() | |||||
{ | |||||
pft_cleanup | |||||
} | |||||
# | # | ||||
# Test that rdr works for multiple TCP with same srcip and srcport. | # Test that rdr works for multiple TCP with same srcip and srcport. | ||||
# | # | ||||
# Four jails, a, b, c, d, are used: | # Four jails, a, b, c, d, are used: | ||||
# - jail d runs a server on port 8888, | # - jail d runs a server on port 8888, | ||||
# - jail a makes connections to the server, routed through jails b and c, | # - jail a makes connections to the server, routed through jails b and c, | ||||
# - jail b uses NAT to rewrite source addresses and ports to the same 2-tuple, | # - jail b uses NAT to rewrite source addresses and ports to the same 2-tuple, | ||||
# avoiding the need to use SO_REUSEADDR in jail a, | # avoiding the need to use SO_REUSEADDR in jail a, | ||||
# - jail c uses a redirect rule to map the destination address to the same | # - jail c uses a redirect rule to map the destination address to the same | ||||
# address and port, resulting in a NAT state conflict. | # address and port, resulting in a NAT state conflict. | ||||
# | # | ||||
# In this case, the rdr rule should also rewrite the source port (again) to | # In this case, the rdr rule should also rewrite the source port (again) to | ||||
# resolve the state conflict. | # resolve the state conflict. | ||||
# | # | ||||
srcport_body() | srcport_setup() | ||||
{ | { | ||||
pft_init | pft_init | ||||
j="rdr:srcport" | j="rdr:srcport" | ||||
epair1=$(vnet_mkepair) | epair1=$(vnet_mkepair) | ||||
epair2=$(vnet_mkepair) | epair2=$(vnet_mkepair) | ||||
epair3=$(vnet_mkepair) | epair3=$(vnet_mkepair) | ||||
Show All 26 Lines | srcport_setup() | ||||
# configure addresses for d | # configure addresses for d | ||||
jexec ${j}d ifconfig lo0 up | jexec ${j}d ifconfig lo0 up | ||||
jexec ${j}d ifconfig ${epair3}b inet 203.0.113.50/24 up | jexec ${j}d ifconfig ${epair3}b inet 203.0.113.50/24 up | ||||
jexec ${j}b sysctl net.inet.ip.forwarding=1 | jexec ${j}b sysctl net.inet.ip.forwarding=1 | ||||
jexec ${j}c sysctl net.inet.ip.forwarding=1 | jexec ${j}c sysctl net.inet.ip.forwarding=1 | ||||
jexec ${j}b pfctl -e | jexec ${j}b pfctl -e | ||||
jexec ${j}c pfctl -e | jexec ${j}c pfctl -e | ||||
} | |||||
srcport_common() | |||||
{ | |||||
pft_set_rules ${j}b \ | pft_set_rules ${j}b \ | ||||
"set debug misc" \ | "set debug misc" \ | ||||
"nat on ${epair2}a inet from 198.51.100.0/24 to any -> ${epair2}a static-port" | "${1}" | ||||
pft_set_rules ${j}c \ | pft_set_rules ${j}c \ | ||||
"set debug misc" \ | "set debug misc" \ | ||||
"rdr on ${epair2}b proto tcp from any to ${epair2}b port 7777 -> 203.0.113.50 port 8888" | "${2}" | ||||
jexec ${j}a route add default 198.51.100.1 | jexec ${j}a route add default 198.51.100.1 | ||||
jexec ${j}c route add 198.51.100.0/24 198.51.101.2 | jexec ${j}c route add 198.51.100.0/24 198.51.101.2 | ||||
jexec ${j}d route add 198.51.101.0/24 203.0.113.1 | jexec ${j}d route add 198.51.101.0/24 203.0.113.1 | ||||
jexec ${j}d python3 $(atf_get_srcdir)/rdr-srcport.py & | jexec ${j}d python3 $(atf_get_srcdir)/rdr-srcport.py & | ||||
sleep 1 | sleep 1 | ||||
echo a | jexec ${j}a nc -w 3 -s 198.51.100.50 -p 1234 198.51.101.3 7777 > port1 | echo a | jexec ${j}a nc -w 3 -s 198.51.100.50 -p 1234 198.51.101.3 7777 > port1 | ||||
jexec ${j}a nc -s 198.51.100.51 -p 1234 198.51.101.4 7777 > port2 & | jexec ${j}a nc -s 198.51.100.51 -p 1234 198.51.101.4 7777 > port2 & | ||||
jexec ${j}a nc -s 198.51.100.52 -p 1234 198.51.101.5 7777 > port3 & | jexec ${j}a nc -s 198.51.100.52 -p 1234 198.51.101.5 7777 > port3 & | ||||
sleep 1 | sleep 1 | ||||
atf_check -o inline:"1234" cat port1 | atf_check -o inline:"1234" cat port1 | ||||
atf_check -o match:"[0-9]+" -o not-inline:"1234" cat port2 | atf_check -o match:"[0-9]+" -o not-inline:"1234" cat port2 | ||||
atf_check -o match:"[0-9]+" -o not-inline:"1234" cat port3 | atf_check -o match:"[0-9]+" -o not-inline:"1234" cat port3 | ||||
} | } | ||||
srcport_cleanup() | atf_test_case "srcport_compat" "cleanup" | ||||
srcport_compat_head() | |||||
{ | { | ||||
atf_set descr 'TCP rdr srcport modulation with NAT rules' | |||||
atf_set require.user root | |||||
atf_set require.progs python3 | |||||
atf_set timeout 9999 | |||||
} | |||||
srcport_compat_body() | |||||
{ | |||||
srcport_setup # Sets ${epair_…} variables | |||||
srcport_common \ | |||||
"nat on ${epair2}a inet from 198.51.100.0/24 to any -> ${epair2}a static-port" \ | |||||
"rdr on ${epair2}b proto tcp from any to ${epair2}b port 7777 -> 203.0.113.50 port 8888" | |||||
} | |||||
srcport_compat_cleanup() | |||||
{ | |||||
pft_cleanup | pft_cleanup | ||||
} | } | ||||
atf_test_case "srcport_pass" "cleanup" | |||||
srcport_pass_head() | |||||
{ | |||||
atf_set descr 'TCP rdr srcport modulation with pass/match rules' | |||||
atf_set require.user root | |||||
atf_set require.progs python3 | |||||
atf_set timeout 9999 | |||||
} | |||||
srcport_pass_body() | |||||
{ | |||||
srcport_setup # Sets ${epair_…} variables | |||||
srcport_common \ | |||||
"pass out on ${epair2}a inet from 198.51.100.0/24 to any nat-to ${epair2}a static-port" \ | |||||
"pass in on ${epair2}b proto tcp from any to ${epair2}b port 7777 rdr-to 203.0.113.50 port 8888" | |||||
} | |||||
srcport_pass_cleanup() | |||||
{ | |||||
pft_cleanup | |||||
} | |||||
atf_init_test_cases() | atf_init_test_cases() | ||||
{ | { | ||||
atf_add_test_case "tcp_v6" | atf_add_test_case "tcp_v6_compat" | ||||
atf_add_test_case "srcport" | atf_add_test_case "tcp_v6_pass" | ||||
atf_add_test_case "srcport_compat" | |||||
atf_add_test_case "srcport_pass" | |||||
} | } |