mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
netstack: iptables DNAT revision 2
With this change, we support all the DNS rules intalled by Docker when using custom networks. PiperOrigin-RevId: 582073741
This commit is contained in:
committed by
gVisor bot
parent
7a918a4292
commit
8657560bd1
@@ -197,3 +197,86 @@ func (st *dnatTargetMakerR1) unmarshal(buf []byte, filter stack.IPHeaderFilter)
|
||||
|
||||
return &target, nil
|
||||
}
|
||||
|
||||
type dnatTargetMakerR2 struct {
|
||||
NetworkProtocol tcpip.NetworkProtocolNumber
|
||||
}
|
||||
|
||||
func (st *dnatTargetMakerR2) id() targetID {
|
||||
return targetID{
|
||||
name: DNATTargetName,
|
||||
networkProtocol: st.NetworkProtocol,
|
||||
revision: 2,
|
||||
}
|
||||
}
|
||||
|
||||
func (*dnatTargetMakerR2) marshal(target target) []byte {
|
||||
st := target.(*dnatTarget)
|
||||
nt := linux.XTNATTargetV2{
|
||||
Target: linux.XTEntryTarget{
|
||||
TargetSize: linux.SizeOfXTNATTargetV1,
|
||||
},
|
||||
Range: linux.NFNATRange2{
|
||||
Flags: linux.NF_NAT_RANGE_MAP_IPS | linux.NF_NAT_RANGE_PROTO_SPECIFIED,
|
||||
},
|
||||
}
|
||||
copy(nt.Target.Name[:], DNATTargetName)
|
||||
copy(nt.Range.MinAddr[:], st.Addr.AsSlice())
|
||||
copy(nt.Range.MaxAddr[:], st.Addr.AsSlice())
|
||||
nt.Range.MinProto = htons(st.Port)
|
||||
nt.Range.MaxProto = nt.Range.MinProto
|
||||
|
||||
return marshal.Marshal(&nt)
|
||||
}
|
||||
|
||||
func (st *dnatTargetMakerR2) unmarshal(buf []byte, filter stack.IPHeaderFilter) (target, *syserr.Error) {
|
||||
if size := linux.SizeOfXTNATTargetV2; len(buf) < size {
|
||||
nflog("dnatTargetMakerR2: buf has insufficient size (%d) for DNAT target (%d)", len(buf), size)
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
if p := filter.Protocol; p != header.TCPProtocolNumber && p != header.UDPProtocolNumber {
|
||||
nflog("dnatTargetMakerR2: bad proto %d", p)
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var natRange linux.NFNATRange2
|
||||
natRange.UnmarshalUnsafe(buf[linux.SizeOfXTEntryTarget:])
|
||||
|
||||
// TODO(gvisor.dev/issue/5697): Support port or address ranges.
|
||||
if natRange.MinAddr != natRange.MaxAddr {
|
||||
nflog("dnatTargetMakerR2: MinAddr and MaxAddr are different")
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
if natRange.MinProto != natRange.MaxProto {
|
||||
nflog("dnatTargetMakerR2: MinProto and MaxProto are different")
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
if natRange.BaseProto != 0 {
|
||||
nflog("dnatTargetMakerR2: BaseProto is nonzero")
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/5698): Support other NF_NAT_RANGE flags.
|
||||
if natRange.Flags != linux.NF_NAT_RANGE_MAP_IPS|linux.NF_NAT_RANGE_PROTO_SPECIFIED {
|
||||
nflog("dnatTargetMakerR2: invalid range flags %d", natRange.Flags)
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
target := dnatTarget{
|
||||
DNATTarget: stack.DNATTarget{
|
||||
NetworkProtocol: filter.NetworkProtocol(),
|
||||
Port: ntohs(natRange.MinProto),
|
||||
},
|
||||
}
|
||||
switch st.NetworkProtocol {
|
||||
case header.IPv4ProtocolNumber:
|
||||
target.DNATTarget.Addr = tcpip.AddrFrom4Slice(natRange.MinAddr[:4])
|
||||
case header.IPv6ProtocolNumber:
|
||||
target.DNATTarget.Addr = tcpip.AddrFrom16(natRange.MinAddr)
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid protocol number: %d", st.NetworkProtocol))
|
||||
}
|
||||
|
||||
return &target, nil
|
||||
}
|
||||
|
||||
@@ -89,6 +89,12 @@ func init() {
|
||||
registerTargetMaker(&dnatTargetMakerR1{
|
||||
NetworkProtocol: header.IPv6ProtocolNumber,
|
||||
})
|
||||
registerTargetMaker(&dnatTargetMakerR2{
|
||||
NetworkProtocol: header.IPv4ProtocolNumber,
|
||||
})
|
||||
registerTargetMaker(&dnatTargetMakerR2{
|
||||
NetworkProtocol: header.IPv6ProtocolNumber,
|
||||
})
|
||||
}
|
||||
|
||||
// The stack package provides some basic, useful targets for us. The following
|
||||
|
||||
@@ -931,7 +931,8 @@ const (
|
||||
snatPort = 43
|
||||
)
|
||||
|
||||
// NATPostSNATUDP tests that the source port/IP in the packets are modified as expected.
|
||||
// NATPostSNATUDP tests that the source port/IP in the packets are modified as
|
||||
// expected. It tests the latest-implemented revision of the SNAT target.
|
||||
type NATPostSNATUDP struct{ localCase }
|
||||
|
||||
var _ TestCase = (*NATPostSNATUDP)(nil)
|
||||
@@ -978,7 +979,7 @@ func (*NATPostSNATUDP) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) er
|
||||
}
|
||||
|
||||
// NATPostSNATTCP tests that the source port/IP in the packets are modified as
|
||||
// expected.
|
||||
// expected. It tests the latest-implemented revision of the SNAT target.
|
||||
type NATPostSNATTCP struct{ localCase }
|
||||
|
||||
var _ TestCase = (*NATPostSNATTCP)(nil)
|
||||
@@ -1038,7 +1039,7 @@ func (*NATPostSNATTCP) LocalAction(ctx context.Context, ip net.IP, ipv6 bool) er
|
||||
}
|
||||
|
||||
// NATOutDNAT tests that the source port/IP in the packets are modified as
|
||||
// expected.
|
||||
// expected. It tests the latest-implemented revision of the DNAT target.
|
||||
type NATOutDNAT struct{ containerCase }
|
||||
|
||||
var _ TestCase = (*NATOutDNAT)(nil)
|
||||
|
||||
Reference in New Issue
Block a user