REDIRECT, DNAT and SNAT panic the Sentry on hooks they do not support
- Dominant language
- Go
- Stars
- 19.3k
- Forks
- 2k
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 264
Description
A target installed on a hook it does not support is accepted, then panics the Sentry on the first packet that reaches that hook. Every process in the sandbox is killed and runsc exits 2. A container that can configure its own netns can do this to itself with one iptables-legacy command.
Linux refuses the same installs with EINVAL:
```
x_tables: ip_tables: REDIRECT target: used from hooks POSTROUTING, but only usable from PREROUTING/OUTPUT
x_tables: ip_tables: DNAT target: used from hooks POSTROUTING, but only usable from PREROUTING/OUTPUT
x_tables: ip_tables: SNAT target: used from hooks OUTPUT, but only usable from INPUT/POSTROUTING
```
`EmptyNATTable` unsets only Forward (iptables.go:250). A nat rule can be installed on the other four hooks.
Each rule ran at least twice over loopback with `--network=none`, with the same result each time:
| rule | host kernel | runsc install | runsc, first packet |
| --- | --- | --- | --- |
| `-t nat -A POSTROUTING -j REDIRECT --to-ports 1234` | EINVAL | accepted | panic, exit 2 |
| `-t nat -A INPUT -j REDIRECT --to-ports 1234` | EINVAL | accepted | panic, exit 2 |
| `-t nat -A POSTROUTING -j DNAT --to-destination 127.0.0.1:1234` | EINVAL | accepted | panic, exit 2 |
| `-t nat -A OUTPUT -j SNAT --to-source 127.0.0.1` | EINVAL | accepted | panic, exit 2 |
| `-t nat -A OUTPUT -j REDIRECT --to-ports 1234` | accepted | accepted | no panic, exit 0 |
| no rule | - | - | no panic, exit 0 |
Three lines in `iptables_targets.go` raise the table's four panics:
```
panic: redirect target is supported only on output and prerouting hooks :281
panic: Postrouting not supported for DNAT :234
panic: Output not supported :379
```
`RejectIPv4Target` and `RejectIPv6Target` panic the same way on Prerouting and Postrouting, at lines 93 and 140. REJECT is refused outside the filter table at install time, and the filter table has no PREROUTING or POSTROUTING chain, so no setsockopt reaches those two panics. `MasqueradeTarget` panics on every hook but Postrouting, at line 408. Netfilter registers no MASQUERADE maker, so no iptables rule can install it.
The host needs iptables-legacy and nc, because `runsc do` uses the host filesystem:
```sh
cat > /tmp/repro.sh <<'SH'
#!/bin/sh
iptables-legacy -t nat -A POSTROUTING -p tcp -j REDIRECT --to-ports 1234
echo "install exit=$?"
nc -w 2 127.0.0.1 9
echo "reached the end"
SH
chmod +x /tmp/repro.sh
sudo runsc --network=none --net-raw --ignore-cgroups --platform=systrap --debug --debug-log=/tmp/runsc-log/ do /tmp/repro.sh
```
The install is accepted, then runsc exits 2 before the script reaches its last line. The panic is in the boot log:
```
panic: redirect target is supported only on output and prerouting hooks
gvisor.dev/gvisor/pkg/tcpip/stack.(*RedirectTarget).Action(...)
pkg/tcpip/stack/iptables_targets.go:281 +0x190
gvisor.dev/gvisor/pkg/tcpip/stack.(*IPTables).checkRule(...)
pkg/tcpip/stack/iptables.go:784 +0x282
gvisor.dev/gvisor/pkg/tcpip/stack.(*IPTables).checkNAT(...)
pkg/tcpip/stack/iptables.go:609 +0x147
gvisor.dev/gvisor/pkg/tcpip/stack.(*IPTables).CheckPostrouting(...)
pkg/tcpip/stack/iptables.go:580 +0x29f
gvisor.dev/gvisor/pkg/tcpip/network/ipv4.(*endpoint).writePacketPostRouting(...)
pkg/tcpip/network/ipv4/ipv4.go:667 +0xd1
```
Proposed fix in #14509.
Contributor guide
Research direction
Start with pkg/tcpip/stack/iptables_targets.go and the hook validation paths in pkg/tcpip/stack/iptables.go, then reproduce the POSTROUTING REDIRECT case with the provided runsc script. Trace each listed target and hook combination, and verify that unsupported installs are rejected without a panic or sandbox exit when the first packet is sent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, linux
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100