summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/iptables
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2020-02-14 17:19:32 -0800
committerKevin Krakauer <krakauer@google.com>2020-02-26 11:04:00 -0800
commit408979e619c4b5df74503c7a887aaaa06fd0d730 (patch)
tree45c8cae6cad967802f28defd96a72a8f5f308771 /pkg/tcpip/iptables
parentb8f56c79be40d9c75f4e2f279c9d821d1c1c3569 (diff)
iptables: filter by IP address (and range)
Enables commands such as: $ iptables -A INPUT -d 127.0.0.1 -j ACCEPT $ iptables -t nat -A PREROUTING ! -d 127.0.0.1 -j REDIRECT Also adds a bunch of REDIRECT+destination tests.
Diffstat (limited to 'pkg/tcpip/iptables')
-rw-r--r--pkg/tcpip/iptables/iptables.go28
-rw-r--r--pkg/tcpip/iptables/types.go12
2 files changed, 37 insertions, 3 deletions
diff --git a/pkg/tcpip/iptables/iptables.go b/pkg/tcpip/iptables/iptables.go
index dbaccbb36..262b6448d 100644
--- a/pkg/tcpip/iptables/iptables.go
+++ b/pkg/tcpip/iptables/iptables.go
@@ -240,9 +240,8 @@ func (it *IPTables) checkChain(hook Hook, pkt tcpip.PacketBuffer, table Table, r
func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) (RuleVerdict, int) {
rule := table.Rules[ruleIdx]
- // First check whether the packet matches the IP header filter.
- // TODO(gvisor.dev/issue/170): Support other fields of the filter.
- if rule.Filter.Protocol != 0 && rule.Filter.Protocol != header.IPv4(pkt.NetworkHeader).TransportProtocol() {
+ // Check whether the packet matches the IP header filter.
+ if !filterMatch(rule.Filter, header.IPv4(pkt.NetworkHeader)) {
// Continue on to the next rule.
return RuleJump, ruleIdx + 1
}
@@ -263,3 +262,26 @@ func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ru
// All the matchers matched, so run the target.
return rule.Target.Action(pkt)
}
+
+func filterMatch(filter IPHeaderFilter, hdr header.IPv4) bool {
+ // TODO(gvisor.dev/issue/170): Support other fields of the filter.
+ // Check the transport protocol.
+ if filter.Protocol != 0 && filter.Protocol != hdr.TransportProtocol() {
+ return false
+ }
+
+ // Check the destination IP.
+ dest := hdr.DestinationAddress()
+ matches := true
+ for i := range filter.Dst {
+ if dest[i]&filter.DstMask[i] != filter.Dst[i] {
+ matches = false
+ break
+ }
+ }
+ if matches == filter.DstInvert {
+ return false
+ }
+
+ return true
+}
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
index 7d032fd23..e7fcf6bff 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -144,6 +144,18 @@ type Rule struct {
type IPHeaderFilter struct {
// Protocol matches the transport protocol.
Protocol tcpip.TransportProtocolNumber
+
+ // Dst matches the destination IP address.
+ Dst tcpip.Address
+
+ // DstMask masks bits of the destination IP address when comparing with
+ // Dst.
+ DstMask tcpip.Address
+
+ // DstInvert inverts the meaning of the destination IP check, i.e. when
+ // true the filter will match packets that fail the destination
+ // comparison.
+ DstInvert bool
}
// A Matcher is the interface for matching packets.