diff --git a/clients/clients.go b/clients/clients.go index cb76419..a029b83 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -37,6 +37,7 @@ type WgConfig struct { type Target struct { SourcePrefix string `json:"sourcePrefix"` DestPrefix string `json:"destPrefix"` + RewriteTo string `json:"rewriteTo,omitempty"` PortRange []PortRange `json:"portRange,omitempty"` } @@ -472,6 +473,15 @@ func (s *WireGuardService) ensureTargets(targets []Target) error { return fmt.Errorf("invalid CIDR %s: %v", target.DestPrefix, err) } + var rewriteTo netip.Prefix + if target.RewriteTo != "" { + rewriteTo, err = netip.ParsePrefix(target.RewriteTo) + if err != nil { + logger.Info("Invalid CIDR %s: %v", target.RewriteTo, err) + continue + } + } + var portRanges []netstack2.PortRange for _, pr := range target.PortRange { portRanges = append(portRanges, netstack2.PortRange{ @@ -480,7 +490,7 @@ func (s *WireGuardService) ensureTargets(targets []Target) error { }) } - s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, portRanges) + s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, rewriteTo, portRanges) logger.Info("Added target subnet from %s to %s with port ranges: %v", target.SourcePrefix, target.DestPrefix, target.PortRange) } @@ -864,6 +874,15 @@ func (s *WireGuardService) handleAddTarget(msg websocket.WSMessage) { continue } + var rewriteTo netip.Prefix + if target.RewriteTo != "" { + rewriteTo, err = netip.ParsePrefix(target.RewriteTo) + if err != nil { + logger.Info("Invalid CIDR %s: %v", target.RewriteTo, err) + continue + } + } + var portRanges []netstack2.PortRange for _, pr := range target.PortRange { portRanges = append(portRanges, netstack2.PortRange{ @@ -872,7 +891,7 @@ func (s *WireGuardService) handleAddTarget(msg websocket.WSMessage) { }) } - s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, portRanges) + s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, rewriteTo, portRanges) logger.Info("Added target subnet from %s to %s with port ranges: %v", target.SourcePrefix, target.DestPrefix, target.PortRange) } @@ -979,6 +998,15 @@ func (s *WireGuardService) handleUpdateTarget(msg websocket.WSMessage) { continue } + var rewriteTo netip.Prefix + if target.RewriteTo != "" { + rewriteTo, err = netip.ParsePrefix(target.RewriteTo) + if err != nil { + logger.Info("Invalid CIDR %s: %v", target.RewriteTo, err) + continue + } + } + var portRanges []netstack2.PortRange for _, pr := range target.PortRange { portRanges = append(portRanges, netstack2.PortRange{ @@ -987,7 +1015,7 @@ func (s *WireGuardService) handleUpdateTarget(msg websocket.WSMessage) { }) } - s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, portRanges) + s.tnet.AddProxySubnetRule(sourcePrefix, destPrefix, rewriteTo, portRanges) logger.Info("Added target subnet from %s to %s with port ranges: %v", target.SourcePrefix, target.DestPrefix, target.PortRange) } } diff --git a/netstack2/proxy.go b/netstack2/proxy.go index 8e37f12..625a8af 100644 --- a/netstack2/proxy.go +++ b/netstack2/proxy.go @@ -27,6 +27,7 @@ type PortRange struct { type SubnetRule struct { SourcePrefix netip.Prefix // Source IP prefix (who is sending) DestPrefix netip.Prefix // Destination IP prefix (where it's going) + RewriteTo netip.Prefix // Optional rewrite address for destination PortRanges []PortRange // empty slice means all ports allowed } @@ -51,7 +52,7 @@ func NewSubnetLookup() *SubnetLookup { // AddSubnet adds a subnet rule with source and destination prefixes and optional port restrictions // If portRanges is nil or empty, all ports are allowed for this subnet -func (sl *SubnetLookup) AddSubnet(sourcePrefix, destPrefix netip.Prefix, portRanges []PortRange) { +func (sl *SubnetLookup) AddSubnet(sourcePrefix, destPrefix, rewriteTo netip.Prefix, portRanges []PortRange) { sl.mu.Lock() defer sl.mu.Unlock() @@ -63,6 +64,7 @@ func (sl *SubnetLookup) AddSubnet(sourcePrefix, destPrefix netip.Prefix, portRan sl.rules[key] = &SubnetRule{ SourcePrefix: sourcePrefix, DestPrefix: destPrefix, + RewriteTo: rewriteTo, PortRanges: portRanges, } } @@ -200,11 +202,11 @@ func NewProxyHandler(options ProxyHandlerOptions) (*ProxyHandler, error) { // sourcePrefix: The IP prefix of the peer sending the data // destPrefix: The IP prefix of the destination // If portRanges is nil or empty, all ports are allowed for this subnet -func (p *ProxyHandler) AddSubnetRule(sourcePrefix, destPrefix netip.Prefix, portRanges []PortRange) { +func (p *ProxyHandler) AddSubnetRule(sourcePrefix, destPrefix, rewriteTo netip.Prefix, portRanges []PortRange) { if p == nil || !p.enabled { return } - p.subnetLookup.AddSubnet(sourcePrefix, destPrefix, portRanges) + p.subnetLookup.AddSubnet(sourcePrefix, destPrefix, rewriteTo, portRanges) } // RemoveSubnetRule removes a subnet from the proxy handler diff --git a/netstack2/tun.go b/netstack2/tun.go index 2cd00ab..b5b5a08 100644 --- a/netstack2/tun.go +++ b/netstack2/tun.go @@ -350,10 +350,10 @@ func (net *Net) ListenUDP(laddr *net.UDPAddr) (*gonet.UDPConn, error) { // AddProxySubnetRule adds a subnet rule to the proxy handler // If portRanges is nil or empty, all ports are allowed for this subnet -func (net *Net) AddProxySubnetRule(sourcePrefix, destPrefix netip.Prefix, portRanges []PortRange) { +func (net *Net) AddProxySubnetRule(sourcePrefix, destPrefix, rewriteTo netip.Prefix, portRanges []PortRange) { tun := (*netTun)(net) if tun.proxyHandler != nil { - tun.proxyHandler.AddSubnetRule(sourcePrefix, destPrefix, portRanges) + tun.proxyHandler.AddSubnetRule(sourcePrefix, destPrefix, rewriteTo, portRanges) } }