Documentation
¶
Overview ¶
Package nat implements IPv4 network address translation between two L3 networks.
Unlike the slirp package (which NATs to the real host network via net.Dial), this NAT operates entirely within the pktkit virtual network, translating addresses between an inside (private) and outside (public) L3 interface.
It handles TCP, UDP, and ICMP (echo + error messages), including proper rewriting of embedded headers in ICMP error payloads.
NAT64 translates between IPv6 and IPv4 packets, allowing IPv6-only clients to reach IPv4 destinations via IPv4-mapped IPv6 addresses (::ffff:x.x.x.x).
Inside() faces the IPv6 network; Outside() faces the IPv4 network.
Index ¶
- type Defragger
- type Expectation
- type FTPHelper
- func (h *FTPHelper) Close() error
- func (h *FTPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *FTPHelper) Name() string
- func (h *FTPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *FTPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type H323Helper
- func (h *H323Helper) Close() error
- func (h *H323Helper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *H323Helper) Name() string
- func (h *H323Helper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *H323Helper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type Helper
- type IRCHelper
- func (h *IRCHelper) Close() error
- func (h *IRCHelper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *IRCHelper) Name() string
- func (h *IRCHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *IRCHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type LocalHelper
- type NAT
- func (n *NAT) AddExpectation(e Expectation)
- func (n *NAT) AddHelper(h Helper)
- func (n *NAT) AddPortForward(pf PortForward) error
- func (n *NAT) AllocOutsidePort(proto uint8) uint16
- func (n *NAT) Close() error
- func (n *NAT) ConnectL3(dev pktkit.L3Device) (func() error, error)
- func (n *NAT) CreateMapping(proto uint8, insideIP netip.Addr, insidePort uint16) uint16
- func (n *NAT) EnableDefrag()
- func (n *NAT) EnableUPnP(cfg UPnPConfig) error
- func (n *NAT) Inside() pktkit.L3Device
- func (n *NAT) InsideAddr() netip.Addr
- func (n *NAT) ListPortForwards() []PortForward
- func (n *NAT) Outside() pktkit.L3Device
- func (n *NAT) OutsideAddr() netip.Addr
- func (n *NAT) RemovePortForward(proto uint8, outsidePort uint16) error
- func (n *NAT) SendInside(pkt pktkit.Packet)
- type NAT64
- type NATMapping
- type PPTPHelper
- func (h *PPTPHelper) Close() error
- func (h *PPTPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *PPTPHelper) Name() string
- func (h *PPTPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *PPTPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type PacketHelper
- type PortForward
- type SIPHelper
- func (h *SIPHelper) Close() error
- func (h *SIPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *SIPHelper) Name() string
- func (h *SIPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *SIPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type TFTPHelper
- func (h *TFTPHelper) Close() error
- func (h *TFTPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
- func (h *TFTPHelper) Name() string
- func (h *TFTPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- func (h *TFTPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
- type UPnPConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Defragger ¶
type Defragger struct {
// contains filtered or unexported fields
}
Defragger reassembles fragmented IPv4 packets.
type Expectation ¶
type Expectation struct {
Proto uint8 // expected protocol (TCP/UDP)
RemoteIP netip.Addr // expected remote IP (zero = any)
RemotePort uint16 // expected remote port (0 = any)
InsideIP netip.Addr // where to forward
InsidePort uint16 // inside destination port
Expires time.Time
}
Expectation describes a future connection that the NAT should accept and translate automatically. Helpers create expectations for related connections (e.g., FTP data channels, RTP media streams).
type FTPHelper ¶
type FTPHelper struct{}
FTPHelper is an Application Layer Gateway for FTP (RFC 959). It rewrites PORT/EPRT commands in outbound traffic and 227/229 responses in inbound traffic so that active and passive mode data connections work through the NAT.
func (*FTPHelper) MatchOutbound ¶
MatchOutbound returns true for TCP connections to port 21 (FTP control).
func (*FTPHelper) ProcessInbound ¶
ProcessInbound inspects inbound TCP payload for 227 and 229 responses, rewrites passive-mode addresses, and creates expectations.
func (*FTPHelper) ProcessOutbound ¶
ProcessOutbound inspects outbound TCP payload for PORT and EPRT commands, rewrites the embedded IP:port to the NAT's outside address, and creates expectations for the resulting inbound data connections.
type H323Helper ¶
type H323Helper struct{}
H323Helper is a simplified ALG for the H.323 VoIP protocol suite.
H.323 uses ASN.1 PER (Packed Encoding Rules) for its signaling messages, which makes full parsing extremely complex. This implementation uses a heuristic approach: it searches for 4-byte IPv4 address patterns and 6-byte transport address patterns (4-byte IP + 2-byte port) in the TCP payload, replacing inside addresses with outside addresses. While imperfect, this covers the majority of real-world H.323 NAT traversal cases where the addresses appear as contiguous binary values.
func (*H323Helper) Close ¶
func (h *H323Helper) Close() error
func (*H323Helper) MatchOutbound ¶
func (h *H323Helper) MatchOutbound(proto uint8, dstPort uint16) bool
MatchOutbound returns true for TCP traffic to port 1720 (Q.931/H.225).
func (*H323Helper) Name ¶
func (h *H323Helper) Name() string
func (*H323Helper) ProcessInbound ¶
func (h *H323Helper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessInbound searches the TCP payload for binary representations of the outside IP address and replaces them with the inside IP.
func (*H323Helper) ProcessOutbound ¶
func (h *H323Helper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessOutbound searches the TCP payload for binary representations of the inside IP address and replaces them with the outside IP. When a 6-byte transport address (IP + port) is found, it creates NAT expectations for the associated H.245 or RTP channels.
type Helper ¶
Helper is an optional NAT module loaded via NAT.AddHelper.
type IRCHelper ¶
type IRCHelper struct {
// contains filtered or unexported fields
}
IRCHelper is an Application Layer Gateway for IRC DCC (Direct Client-to-Client).
DCC commands embed the sender's IP address (as a 32-bit decimal integer) and a TCP port in the PRIVMSG payload. This helper rewrites those values to the NAT's outside address and an allocated outside port, and creates expectations so the incoming DCC connection is forwarded correctly.
func NewIRCHelper ¶
NewIRCHelper returns a new IRC DCC ALG helper. If no ports are specified, the default IRC port 6667 is used.
func (*IRCHelper) MatchOutbound ¶
MatchOutbound returns true for TCP connections to any of the configured IRC ports.
func (*IRCHelper) ProcessInbound ¶
ProcessInbound is a no-op for IRC DCC. Incoming DCC connections are handled by the expectations registered in ProcessOutbound.
func (*IRCHelper) ProcessOutbound ¶
ProcessOutbound inspects outbound TCP payload for DCC SEND and DCC CHAT commands, rewrites the embedded IP and port to the NAT's outside address, and creates expectations for incoming DCC connections.
type LocalHelper ¶
LocalHelper handles packets destined for the NAT's own inside IP address (e.g., UPnP control requests, SSDP discovery). Returns true if the packet was consumed and should not be processed further.
type NAT ¶
type NAT struct {
// contains filtered or unexported fields
}
NAT performs IPv4 network address translation between two L3 networks. Inside() faces the private network (acts as default gateway). Outside() faces the upstream network (uses a public IP).
For multi-tenant use (e.g. WireGuard), call ConnectL3 to create namespace-isolated inside L3Devices. Each namespace's connections are tracked independently, allowing overlapping inside IPs.
func (*NAT) AddExpectation ¶
func (n *NAT) AddExpectation(e Expectation)
AddExpectation registers an expected future connection.
func (*NAT) AddPortForward ¶
func (n *NAT) AddPortForward(pf PortForward) error
AddPortForward creates a static port mapping. Inbound connections to outsidePort are forwarded to insideIP:insidePort. Returns an error if the outside port is already forwarded to a different inside IP.
func (*NAT) AllocOutsidePort ¶
AllocOutsidePort allocates an outside port for use by helpers. Returns 0 if no ports are available.
func (*NAT) ConnectL3 ¶
ConnectL3 implements pktkit.L3Connector. It creates a namespace-isolated inside L3Device. Packets from the device are tracked with a unique namespace ID, so multiple devices can use overlapping inside IPs without conflict. The returned cleanup function removes the namespace and its mappings.
func (*NAT) CreateMapping ¶
CreateMapping creates a NAT mapping for use by helpers. Returns the allocated outside port.
func (*NAT) EnableDefrag ¶
func (n *NAT) EnableDefrag()
EnableDefrag activates IP defragmentation on the NAT.
func (*NAT) EnableUPnP ¶
func (n *NAT) EnableUPnP(cfg UPnPConfig) error
EnableUPnP creates and registers a UPnP IGD helper on this NAT. Clients on the inside network can discover the NAT via SSDP and manage port forwarding through SOAP requests.
func (*NAT) InsideAddr ¶
InsideAddr returns the NAT's inside IP address.
func (*NAT) ListPortForwards ¶
func (n *NAT) ListPortForwards() []PortForward
ListPortForwards returns all active static port mappings.
func (*NAT) OutsideAddr ¶
OutsideAddr returns the NAT's outside IP address. Useful for helpers that need to know the public IP.
func (*NAT) RemovePortForward ¶
RemovePortForward removes a static port mapping.
func (*NAT) SendInside ¶
SendInside sends a raw IP packet out through the inside interface. Used by helpers (e.g., UPnP) that need to send responses to inside clients.
type NAT64 ¶
type NAT64 struct {
// contains filtered or unexported fields
}
NAT64 performs IPv6-to-IPv4 network address translation. Inside() faces the IPv6 network; Outside() faces the IPv4 network.
type NATMapping ¶
NATMapping provides a read-only view of a NAT mapping for use by helpers.
type PPTPHelper ¶
type PPTPHelper struct {
// contains filtered or unexported fields
}
PPTPHelper is an ALG for the Point-to-Point Tunneling Protocol (PPTP). It tracks PPTP control channel messages (TCP port 1723) to extract Call-IDs used in the associated GRE data tunnel, and creates NAT expectations for the GRE traffic.
Note: GRE traffic uses IP protocol 47 (not TCP or UDP). Full PPTP NAT traversal requires the NAT core to handle GRE packets, including rewriting the Call-ID in the GRE key field (bytes 4-5 of the GRE header for PPTP enhanced GRE). This helper only handles the control signaling; GRE data forwarding is beyond its scope.
func (*PPTPHelper) Close ¶
func (h *PPTPHelper) Close() error
func (*PPTPHelper) MatchOutbound ¶
func (h *PPTPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
MatchOutbound returns true for TCP traffic to port 1723.
func (*PPTPHelper) Name ¶
func (h *PPTPHelper) Name() string
func (*PPTPHelper) ProcessInbound ¶
func (h *PPTPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessInbound parses PPTP control messages from the server side, tracking Call-IDs in reply messages for proper GRE forwarding.
func (*PPTPHelper) ProcessOutbound ¶
func (h *PPTPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessOutbound parses PPTP control messages and tracks Call-IDs. For Outgoing-Call-Request messages, it extracts the Call-ID and creates GRE expectations.
type PacketHelper ¶
type PacketHelper interface {
Helper
// MatchOutbound returns true if this helper handles connections to the
// given protocol and destination port.
MatchOutbound(proto uint8, dstPort uint16) bool
// ProcessOutbound may modify an outbound packet after NAT translation.
// It may call [NAT.AddExpectation] to register expected related connections.
ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
// ProcessInbound may modify an inbound packet after reverse-NAT translation.
ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
}
PacketHelper inspects and modifies packets flowing through the NAT. Used by ALGs (FTP, SIP, etc.) that need to rewrite embedded addresses in application-layer protocols.
type PortForward ¶
type PortForward struct {
Proto uint8
OutsidePort uint16
InsideIP netip.Addr
InsidePort uint16
Description string
Expires time.Time // zero = permanent
}
PortForward is a static port mapping configured on the NAT.
type SIPHelper ¶
type SIPHelper struct{}
SIPHelper is an ALG for the Session Initiation Protocol (SIP), used in VoIP. It rewrites embedded IP addresses and ports in SIP headers (Via, Contact) and SDP bodies (c= connection, m= media lines), and creates expectations for the resulting RTP/RTCP media streams.
func (*SIPHelper) MatchOutbound ¶
MatchOutbound returns true for UDP or TCP traffic to port 5060.
func (*SIPHelper) ProcessInbound ¶
ProcessInbound rewrites outside addresses back to inside addresses in SIP headers and SDP bodies.
func (*SIPHelper) ProcessOutbound ¶
ProcessOutbound rewrites inside addresses to outside addresses in SIP headers and SDP bodies. It creates NAT expectations for RTP/RTCP streams found in SDP media lines.
type TFTPHelper ¶
type TFTPHelper struct{}
TFTPHelper is an Application Layer Gateway for TFTP (RFC 1350).
TFTP uses a well-known port (69) only for the initial request. The server replies from a random ephemeral port, so the NAT needs an expectation to allow the response through. This helper creates that expectation when it sees an outbound RRQ or WRQ.
func (*TFTPHelper) Close ¶
func (h *TFTPHelper) Close() error
func (*TFTPHelper) MatchOutbound ¶
func (h *TFTPHelper) MatchOutbound(proto uint8, dstPort uint16) bool
MatchOutbound returns true for UDP connections to port 69 (TFTP).
func (*TFTPHelper) Name ¶
func (h *TFTPHelper) Name() string
func (*TFTPHelper) ProcessInbound ¶
func (h *TFTPHelper) ProcessInbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessInbound is a no-op for TFTP. The server's response is handled by the expectation registered in ProcessOutbound.
func (*TFTPHelper) ProcessOutbound ¶
func (h *TFTPHelper) ProcessOutbound(n *NAT, pkt pktkit.Packet, m *NATMapping) pktkit.Packet
ProcessOutbound creates an expectation for the TFTP server's reply. The server will respond from its IP on a random ephemeral port to the client's mapped outside port.
type UPnPConfig ¶
type UPnPConfig struct {
ControlPort uint16 // TCP port for the SOAP control server (default 5000)
AllowedPorts [][2]uint16 // allowed outside port ranges; empty means all
MaxMappings int // max total port forwards (0 = unlimited)
MaxPerClient int // max port forwards per inside IP (0 = unlimited)
LeaseDuration time.Duration // max lease duration (0 = permanent allowed)
}
UPnPConfig configures the UPnP IGD helper.