Merge pull request #9866 from Champ-Goblem:netfilter-add-support-for-inverse-dport-sport

PiperOrigin-RevId: 596753796
This commit is contained in:
gVisor bot
2024-01-08 18:05:03 -08:00
4 changed files with 167 additions and 3 deletions
+15 -3
View File
@@ -51,6 +51,7 @@ func (tcpMarshaler) marshal(mr matcher) []byte {
DestinationPortEnd: matcher.destinationPortEnd,
FlagMask: matcher.flagMask,
FlagCompare: matcher.flagCompare,
InverseFlags: matcher.inverseFlags,
}
return marshalEntryMatch(matcherNameTCP, marshal.Marshal(&xttcp))
}
@@ -67,7 +68,8 @@ func (tcpMarshaler) unmarshal(_ IDMapper, buf []byte, filter stack.IPHeaderFilte
matchData.UnmarshalUnsafe(buf)
nflog("parseMatchers: parsed XTTCP: %+v", matchData)
if matchData.Option != 0 || matchData.InverseFlags != 0 {
// Only support inverse dport/sport
if matchData.Option != 0 || matchData.InverseFlags > 2 {
return nil, fmt.Errorf("unsupported TCP matcher flags set")
}
@@ -82,6 +84,7 @@ func (tcpMarshaler) unmarshal(_ IDMapper, buf []byte, filter stack.IPHeaderFilte
destinationPortEnd: matchData.DestinationPortEnd,
flagMask: matchData.FlagMask,
flagCompare: matchData.FlagCompare,
inverseFlags: matchData.InverseFlags,
}, nil
}
@@ -93,6 +96,7 @@ type TCPMatcher struct {
destinationPortEnd uint16
flagMask uint8
flagCompare uint8
inverseFlags uint8
}
// name implements matcher.name.
@@ -142,10 +146,18 @@ func (tm *TCPMatcher) Match(hook stack.Hook, pkt stack.PacketBufferPtr, _, _ str
// Check whether the source and destination ports are within the
// matching range.
if sourcePort := tcpHeader.SourcePort(); sourcePort < tm.sourcePortStart || tm.sourcePortEnd < sourcePort {
// Take into account inverseFlags for DSTPT & SRCPT only
sPort := tcpHeader.SourcePort()
sPortMatch := sPort < tm.sourcePortStart || tm.sourcePortEnd < sPort
sPortMatch = sPortMatch != (tm.inverseFlags&linux.XT_TCP_INV_SRCPT == linux.XT_TCP_INV_SRCPT)
if sPortMatch {
return false, false
}
if destinationPort := tcpHeader.DestinationPort(); destinationPort < tm.destinationPortStart || tm.destinationPortEnd < destinationPort {
dPort := tcpHeader.DestinationPort()
dPortMatch := dPort < tm.destinationPortStart || tm.destinationPortEnd < dPort
dPortMatch = dPortMatch != (tm.inverseFlags&linux.XT_TCP_INV_DSTPT == linux.XT_TCP_INV_DSTPT)
if dPortMatch {
return false, false
}
+68
View File
@@ -57,6 +57,8 @@ func init() {
RegisterTestCase(&FilterInputInterfaceBeginsWith{})
RegisterTestCase(&FilterInputInterfaceInvertDrop{})
RegisterTestCase(&FilterInputInterfaceInvertAccept{})
RegisterTestCase(&FilterInputInvertDportAccept{})
RegisterTestCase(&FilterInputInvertDportDrop{})
}
// FilterInputDropUDP tests that we can drop UDP traffic.
@@ -988,3 +990,69 @@ func (*FilterInputInterfaceInvertAccept) ContainerAction(ctx context.Context, ip
func (*FilterInputInterfaceInvertAccept) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
return connectTCP(ctx, ip, acceptPort, ipv6)
}
// FilterInputInvertDportAccept tests that we can send packets on a negated
// --dport match
type FilterInputInvertDportAccept struct{ baseCase }
var _ TestCase = (*FilterInputInvertDportAccept)(nil)
// Name implements TestCase.Name.
func (*FilterInputInvertDportAccept) Name() string {
return "FilterInputInvertDportAccept"
}
// ContainerAction implements TestCase.ContainerAction.
func (*FilterInputInvertDportAccept) ContainerAction(ctx context.Context, ip net.IP, ipv6 bool) error {
if err := filterTable(ipv6, "-A", "INPUT", "-p", "tcp", "!", "--dport", fmt.Sprintf("%d", dropPort), "-j", "ACCEPT"); err != nil {
return err
}
// Listen for TCP packets on accept port.
return listenTCP(ctx, acceptPort, ipv6)
}
// LocalAction implements TestCase.LocalAction.
func (*FilterInputInvertDportAccept) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
return connectTCP(ctx, ip, acceptPort, ipv6)
}
// FilterInputInvertDportDrop tests that we can send packets on a negated
// --dport match
type FilterInputInvertDportDrop struct{ baseCase }
var _ TestCase = (*FilterInputInvertDportDrop)(nil)
// Name implements TestCase.Name.
func (*FilterInputInvertDportDrop) Name() string {
return "FilterInputInvertDportDrop"
}
// ContainerAction implements TestCase.ContainerAction.
func (*FilterInputInvertDportDrop) ContainerAction(ctx context.Context, ip net.IP, ipv6 bool) error {
if err := filterTable(ipv6, "-A", "INPUT", "-p", "tcp", "!", "--dport", fmt.Sprintf("%d", acceptPort), "-j", "DROP"); err != nil {
return err
}
// Listen for TCP packets on accept port.
timedCtx, cancel := context.WithTimeout(ctx, NegativeTimeout)
defer cancel()
if err := listenTCP(timedCtx, dropPort, ipv6); err == nil {
return fmt.Errorf("connection was established when it shouldnt have been")
} else if !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("error reading: %v", err)
}
return nil
}
// LocalAction implements TestCase.LocalAction.
func (*FilterInputInvertDportDrop) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
timedCtx, cancel := context.WithTimeout(ctx, NegativeTimeout)
defer cancel()
if err := connectTCP(timedCtx, ip, dropPort, ipv6); err == nil {
return fmt.Errorf("connection on %d port was accepted when it should have been dropped", dropPort)
}
return nil
}
+68
View File
@@ -42,6 +42,8 @@ func init() {
RegisterTestCase(&FilterOutputInterfaceBeginsWith{})
RegisterTestCase(&FilterOutputInterfaceInvertDrop{})
RegisterTestCase(&FilterOutputInterfaceInvertAccept{})
RegisterTestCase(&FilterOutputInvertSportAccept{})
RegisterTestCase(&FilterOutputInvertSportDrop{})
}
// FilterOutputDropTCPDestPort tests that connections are not accepted on
@@ -712,3 +714,69 @@ func (*FilterOutputInterfaceInvertAccept) ContainerAction(ctx context.Context, i
func (*FilterOutputInterfaceInvertAccept) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
return connectTCP(ctx, ip, acceptPort, ipv6)
}
// FilterOutputInvertSportAccept tests that we can send packets on a negated
// --sport match
type FilterOutputInvertSportAccept struct{ baseCase }
var _ TestCase = (*FilterOutputInvertSportAccept)(nil)
// Name implements TestCase.Name.
func (*FilterOutputInvertSportAccept) Name() string {
return "FilterOutputInvertSportAccept"
}
// ContainerAction implements TestCase.ContainerAction.
func (*FilterOutputInvertSportAccept) ContainerAction(ctx context.Context, ip net.IP, ipv6 bool) error {
if err := filterTable(ipv6, "-A", "OUTPUT", "-p", "tcp", "!", "--sport", fmt.Sprintf("%d", dropPort), "-j", "ACCEPT"); err != nil {
return err
}
// Listen for TCP packets on accept port.
return listenTCP(ctx, acceptPort, ipv6)
}
// LocalAction implements TestCase.LocalAction.
func (*FilterOutputInvertSportAccept) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
return connectTCP(ctx, ip, acceptPort, ipv6)
}
// FilterOutputInvertSportDrop tests that we can send packets on a negated
// --dport match
type FilterOutputInvertSportDrop struct{ baseCase }
var _ TestCase = (*FilterOutputInvertSportDrop)(nil)
// Name implements TestCase.Name.
func (*FilterOutputInvertSportDrop) Name() string {
return "FilterOutputInvertSportDrop"
}
// ContainerAction implements TestCase.ContainerAction.
func (*FilterOutputInvertSportDrop) ContainerAction(ctx context.Context, ip net.IP, ipv6 bool) error {
if err := filterTable(ipv6, "-A", "OUTPUT", "-p", "tcp", "!", "--sport", fmt.Sprintf("%d", acceptPort), "-j", "DROP"); err != nil {
return err
}
// Listen for TCP packets on accept port.
timedCtx, cancel := context.WithTimeout(ctx, NegativeTimeout)
defer cancel()
if err := listenTCP(timedCtx, dropPort, ipv6); err == nil {
return fmt.Errorf("connection was established when it shouldnt have been")
} else if !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("error reading: %v", err)
}
return nil
}
// LocalAction implements TestCase.LocalAction.
func (*FilterOutputInvertSportDrop) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) error {
timedCtx, cancel := context.WithTimeout(ctx, NegativeTimeout)
defer cancel()
if err := connectTCP(timedCtx, ip, dropPort, ipv6); err == nil {
return fmt.Errorf("connection on %d port was accepted when it should have been dropped", dropPort)
}
return nil
}
+16
View File
@@ -287,6 +287,14 @@ func TestFilterOutputInterfaceInvertAccept(t *testing.T) {
singleTest(t, &FilterOutputInterfaceInvertAccept{})
}
func TestFilterOutputInvertSportAccept(t *testing.T) {
singleTest(t, &FilterOutputInvertSportAccept{})
}
func TestFilterOutputInvertSportDrop(t *testing.T) {
singleTest(t, &FilterOutputInvertSportDrop{})
}
func TestJumpSerialize(t *testing.T) {
singleTest(t, &FilterInputSerializeJump{})
}
@@ -434,6 +442,14 @@ func TestInputInterfaceInvertAccept(t *testing.T) {
singleTest(t, &FilterInputInterfaceInvertAccept{})
}
func TestFilterInputInvertDportAccept(t *testing.T) {
singleTest(t, &FilterInputInvertDportAccept{})
}
func TestFilterInputInvertDportDrop(t *testing.T) {
singleTest(t, &FilterInputInvertDportDrop{})
}
func TestFilterAddrs(t *testing.T) {
tcs := []struct {
ipv6 bool