diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 89960cf3..7ef880d1 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -17,5 +17,9 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn) *context.ConnCo metadata.SrcIP = ip metadata.SrcPort = port } + if ip, port, err := parseAddr(conn.LocalAddr().String()); err == nil { + metadata.InIP = ip + metadata.InPort = port + } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index 99bc433f..53ad46b2 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -16,5 +16,9 @@ func NewHTTPS(request *http.Request, conn net.Conn) *context.ConnContext { metadata.SrcIP = ip metadata.SrcPort = port } + if ip, port, err := parseAddr(conn.LocalAddr().String()); err == nil { + metadata.InIP = ip + metadata.InPort = port + } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index 80b136cd..687e1089 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -25,6 +25,12 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type) *PacketAda metadata.SrcIP = ip metadata.SrcPort = port } + if p, ok := packet.(C.UDPPacketInAddr); ok { + if ip, port, err := parseAddr(p.InAddr().String()); err == nil { + metadata.InIP = ip + metadata.InPort = port + } + } return &PacketAdapter{ UDPPacket: packet, diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index 7fe00dbf..63231611 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -22,6 +22,14 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type) *context.ConnCo metadata.SrcPort = port } } + localAddr := conn.LocalAddr() + // Filter when net.Addr interface is nil + if localAddr != nil { + if ip, port, err := parseAddr(localAddr.String()); err == nil { + metadata.InIP = ip + metadata.InPort = port + } + } return context.NewConnContext(conn, metadata) } diff --git a/constant/adapters.go b/constant/adapters.go index 71613487..47826a74 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -202,3 +202,7 @@ type UDPPacket interface { // LocalAddr returns the source IP/Port of packet LocalAddr() net.Addr } + +type UDPPacketInAddr interface { + InAddr() net.Addr +} diff --git a/constant/metadata.go b/constant/metadata.go index 61a98be3..dcddcd8b 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -115,6 +115,8 @@ type Metadata struct { DstIP netip.Addr `json:"destinationIP"` SrcPort string `json:"sourcePort"` DstPort string `json:"destinationPort"` + InIP netip.Addr `json:"inboundIP"` + InPort string `json:"inboundPort"` Host string `json:"host"` DNSMode DNSMode `json:"dnsMode"` Uid *int32 `json:"uid"` diff --git a/constant/rule.go b/constant/rule.go index 223dec6e..28c629a0 100644 --- a/constant/rule.go +++ b/constant/rule.go @@ -13,6 +13,7 @@ const ( SrcIPSuffix SrcPort DstPort + InPort Process ProcessPath RuleSet @@ -52,6 +53,8 @@ func (rt RuleType) String() string { return "SrcPort" case DstPort: return "DstPort" + case InPort: + return "InPort" case Process: return "Process" case ProcessPath: diff --git a/listener/socks/utils.go b/listener/socks/utils.go index 28dfef72..4c53b9e5 100644 --- a/listener/socks/utils.go +++ b/listener/socks/utils.go @@ -35,3 +35,7 @@ func (c *packet) LocalAddr() net.Addr { func (c *packet) Drop() { pool.Put(c.bufRef) } + +func (c *packet) InAddr() net.Addr { + return c.pc.LocalAddr() +} diff --git a/listener/tproxy/packet.go b/listener/tproxy/packet.go index 8aa3e9bf..d60f0ac2 100644 --- a/listener/tproxy/packet.go +++ b/listener/tproxy/packet.go @@ -7,6 +7,7 @@ import ( ) type packet struct { + pc net.PacketConn lAddr *net.UDPAddr buf []byte } @@ -35,3 +36,7 @@ func (c *packet) LocalAddr() net.Addr { func (c *packet) Drop() { pool.Put(c.buf) } + +func (c *packet) InAddr() net.Addr { + return c.pc.LocalAddr() +} diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index c7e6d99e..57120785 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -81,6 +81,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { target := socks5.ParseAddrToSocksAddr(rAddr) pkt := &packet{ + pc: pc, lAddr: lAddr, buf: buf, } diff --git a/rules/common/port.go b/rules/common/port.go index 270e5b20..3b7ea1fc 100644 --- a/rules/common/port.go +++ b/rules/common/port.go @@ -13,22 +13,23 @@ type Port struct { *Base adapter string port string - isSource bool + ruleType C.RuleType portList []utils.Range[uint16] } func (p *Port) RuleType() C.RuleType { - if p.isSource { - return C.SrcPort - } - return C.DstPort + return p.ruleType } func (p *Port) Match(metadata *C.Metadata) (bool, string) { - if p.isSource { - return p.matchPortReal(metadata.SrcPort), p.adapter + targetPort := metadata.DstPort + switch p.ruleType { + case C.InPort: + targetPort = metadata.InPort + case C.SrcPort: + targetPort = metadata.SrcPort } - return p.matchPortReal(metadata.DstPort), p.adapter + return p.matchPortReal(targetPort), p.adapter } func (p *Port) Adapter() string { @@ -51,7 +52,7 @@ func (p *Port) matchPortReal(portRef string) bool { return false } -func NewPort(port string, adapter string, isSource bool) (*Port, error) { +func NewPort(port string, adapter string, ruleType C.RuleType) (*Port, error) { ports := strings.Split(port, "/") if len(ports) > 28 { return nil, fmt.Errorf("%s, too many ports to use, maximum support 28 ports", errPayload.Error()) @@ -95,7 +96,7 @@ func NewPort(port string, adapter string, isSource bool) (*Port, error) { Base: &Base{}, adapter: adapter, port: port, - isSource: isSource, + ruleType: ruleType, portList: portRange, }, nil } diff --git a/rules/logic/logic_test.go b/rules/logic/logic_test.go index 0410873e..da061d71 100644 --- a/rules/logic/logic_test.go +++ b/rules/logic/logic_test.go @@ -33,9 +33,11 @@ func ParseRule(tp, payload, target string, params []string, subRules *map[string case "SRC-IP-SUFFIX": parsed, parseErr = RC.NewIPSuffix(payload, target, true, true) case "SRC-PORT": - parsed, parseErr = RC.NewPort(payload, target, true) + parsed, parseErr = RC.NewPort(payload, target, C.SrcPort) case "DST-PORT": - parsed, parseErr = RC.NewPort(payload, target, false) + parsed, parseErr = RC.NewPort(payload, target, C.DstPort) + case "IN-PORT": + parsed, parseErr = RC.NewPort(payload, target, C.InPort) case "PROCESS-NAME": parsed, parseErr = RC.NewProcess(payload, target, true) case "PROCESS-PATH": diff --git a/rules/parser.go b/rules/parser.go index 6f9e229f..4e1d9044 100644 --- a/rules/parser.go +++ b/rules/parser.go @@ -32,9 +32,11 @@ func ParseRule(tp, payload, target string, params []string, subRules *map[string case "SRC-IP-SUFFIX": parsed, parseErr = RC.NewIPSuffix(payload, target, true, true) case "SRC-PORT": - parsed, parseErr = RC.NewPort(payload, target, true) + parsed, parseErr = RC.NewPort(payload, target, C.SrcPort) case "DST-PORT": - parsed, parseErr = RC.NewPort(payload, target, false) + parsed, parseErr = RC.NewPort(payload, target, C.DstPort) + case "IN-PORT": + parsed, parseErr = RC.NewPort(payload, target, C.InPort) case "PROCESS-NAME": parsed, parseErr = RC.NewProcess(payload, target, true) case "PROCESS-PATH":