Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/proxyman/inbound/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
}
ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: net.DestinationFromAddr(conn.RemoteAddr()),
Local: net.DestinationFromAddr(conn.LocalAddr()),
Gateway: net.TCPDestination(w.address, w.port),
Tag: w.tag,
Conn: conn,
Expand Down Expand Up @@ -321,8 +322,10 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
outbounds[0].Target = originalDest
}
ctx = session.ContextWithOutbounds(ctx, outbounds)

ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: source,
Local: net.DestinationFromAddr(w.hub.Addr()),
Gateway: net.UDPDestination(w.address, w.port),
Tag: w.tag,
})
Expand Down Expand Up @@ -472,6 +475,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
}
ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: net.DestinationFromAddr(conn.RemoteAddr()),
Local: net.DestinationFromAddr(conn.LocalAddr()),
Gateway: net.UnixDestination(w.address),
Tag: w.tag,
Conn: conn,
Expand Down
244 changes: 132 additions & 112 deletions app/router/command/command.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions app/router/command/command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ message RoutingContext {
map<string, string> Attributes = 10;
repeated string OutboundGroupTags = 11;
string OutboundTag = 12;
repeated bytes LocalIPs = 13;
uint32 LocalPort = 14;
}

// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
Expand Down
10 changes: 10 additions & 0 deletions app/router/command/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ func (c routingContext) GetTargetPort() net.Port {
return net.Port(c.RoutingContext.GetTargetPort())
}

func (c routingContext) GetLocalIPs() []net.IP {
return mapBytesToIPs(c.RoutingContext.GetLocalIPs())
}

func (c routingContext) GetLocalPort() net.Port {
return net.Port(c.RoutingContext.GetLocalPort())
}

func (c routingContext) GetRuleTag() string {
return ""
}
Expand All @@ -54,8 +62,10 @@ var fieldMap = map[string]func(*RoutingContext, routing.Route){
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
"ip_source": func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
"ip_target": func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
"ip_local": func(s *RoutingContext, r routing.Route) { s.LocalIPs = mapIPsToBytes(r.GetLocalIPs()) },
"port_source": func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
"port_target": func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
"port_local": func(s *RoutingContext, r routing.Route) { s.LocalPort = uint32(r.GetLocalPort()) },
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
Expand Down
39 changes: 26 additions & 13 deletions app/router/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {

type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
onSource bool
asType string // local, source, target
}

func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher
for _, geoip := range geoips {
matcher, err := GlobalGeoIPContainer.Add(geoip)
Expand All @@ -128,7 +128,7 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e

matcher := &MultiGeoIPMatcher{
matchers: matchers,
onSource: onSource,
asType: asType,
}

return matcher, nil
Expand All @@ -137,11 +137,18 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e
// Apply implements Condition.
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
var ips []net.IP
if m.onSource {

switch m.asType {
case "local":
ips = ctx.GetLocalIPs()
case "source":
ips = ctx.GetSourceIPs()
} else {
case "target":
ips = ctx.GetTargetIPs()
default:
panic("unreachable, asType should be local or source or target")
}

for _, ip := range ips {
for _, matcher := range m.matchers {
if matcher.Match(ip) {
Expand All @@ -153,25 +160,31 @@ func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
}

type PortMatcher struct {
port net.MemoryPortList
onSource bool
port net.MemoryPortList
asType string // local, source, target
}

// NewPortMatcher create a new port matcher that can match source or destination port
func NewPortMatcher(list *net.PortList, onSource bool) *PortMatcher {
// NewPortMatcher create a new port matcher that can match source or local or destination port
func NewPortMatcher(list *net.PortList, asType string) *PortMatcher {
return &PortMatcher{
port: net.PortListFromProto(list),
onSource: onSource,
port: net.PortListFromProto(list),
asType: asType,
}
}

// Apply implements Condition.
func (v *PortMatcher) Apply(ctx routing.Context) bool {
if v.onSource {
switch v.asType {
case "local":
return v.port.Contains(ctx.GetLocalPort())
case "source":
return v.port.Contains(ctx.GetSourcePort())
} else {
case "target":
return v.port.Contains(ctx.GetTargetPort())
default:
panic("unreachable, asType should be local or source or target")
}

}

type NetworkMatcher struct {
Expand Down
2 changes: 1 addition & 1 deletion app/router/condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
})
}

matcher, err := NewMultiGeoIPMatcher(geoips, false)
matcher, err := NewMultiGeoIPMatcher(geoips, "target")
common.Must(err)

ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
Expand Down
21 changes: 17 additions & 4 deletions app/router/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,44 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
}

if rr.PortList != nil {
conds.Add(NewPortMatcher(rr.PortList, false))
conds.Add(NewPortMatcher(rr.PortList, "target"))
}

if rr.SourcePortList != nil {
conds.Add(NewPortMatcher(rr.SourcePortList, true))
conds.Add(NewPortMatcher(rr.SourcePortList, "source"))
}

if rr.LocalPortList != nil {
conds.Add(NewPortMatcher(rr.LocalPortList, "local"))
}

if len(rr.Networks) > 0 {
conds.Add(NewNetworkMatcher(rr.Networks))
}

if len(rr.Geoip) > 0 {
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
cond, err := NewMultiGeoIPMatcher(rr.Geoip, "target")
if err != nil {
return nil, err
}
conds.Add(cond)
}

if len(rr.SourceGeoip) > 0 {
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, "source")
if err != nil {
return nil, err
}
conds.Add(cond)
}

if len(rr.LocalGeoip) > 0 {
cond, err := NewMultiGeoIPMatcher(rr.LocalGeoip, "local")
if err != nil {
return nil, err
}
conds.Add(cond)
errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces")
}

if len(rr.Protocol) > 0 {
Expand Down
Loading
Loading