Feature: SOURCE-IP-CIDR rule type (#96)

This commit is contained in:
宋辰文 2019-02-02 21:03:13 +08:00 committed by Dreamacro
parent bfe51e46b0
commit 42d33fe629
10 changed files with 39 additions and 15 deletions

View file

@ -170,6 +170,7 @@ Rule:
- DOMAIN,google.com,Proxy - DOMAIN,google.com,Proxy
- DOMAIN-SUFFIX,ad.com,REJECT - DOMAIN-SUFFIX,ad.com,REJECT
- IP-CIDR,127.0.0.0/8,DIRECT - IP-CIDR,127.0.0.0/8,DIRECT
- SOURCE-IP-CIDR,192.168.1.201/32,DIRECT
- GEOIP,CN,DIRECT - GEOIP,CN,DIRECT
# FINAL would remove after prerelease # FINAL would remove after prerelease
# you also can use `FINAL,Proxy` or `FINAL,,Proxy` now # you also can use `FINAL,Proxy` or `FINAL,,Proxy` now

View file

@ -32,8 +32,10 @@ func (h *HTTPAdapter) Conn() net.Conn {
// NewHTTP is HTTPAdapter generator // NewHTTP is HTTPAdapter generator
func NewHTTP(request *http.Request, conn net.Conn) *HTTPAdapter { func NewHTTP(request *http.Request, conn net.Conn) *HTTPAdapter {
metadata := parseHTTPAddr(request)
metadata.SourceIP = parseSourceIP(conn)
return &HTTPAdapter{ return &HTTPAdapter{
metadata: parseHTTPAddr(request), metadata: metadata,
R: request, R: request,
conn: conn, conn: conn,
} }

View file

@ -7,8 +7,10 @@ import (
// NewHTTPS is HTTPAdapter generator // NewHTTPS is HTTPAdapter generator
func NewHTTPS(request *http.Request, conn net.Conn) *SocketAdapter { func NewHTTPS(request *http.Request, conn net.Conn) *SocketAdapter {
metadata := parseHTTPAddr(request)
metadata.SourceIP = parseSourceIP(conn)
return &SocketAdapter{ return &SocketAdapter{
metadata: parseHTTPAddr(request), metadata: metadata,
conn: conn, conn: conn,
} }
} }

View file

@ -32,6 +32,7 @@ func (s *SocketAdapter) Conn() net.Conn {
func NewSocket(target socks.Addr, conn net.Conn, source C.SourceType) *SocketAdapter { func NewSocket(target socks.Addr, conn net.Conn, source C.SourceType) *SocketAdapter {
metadata := parseSocksAddr(target) metadata := parseSocksAddr(target)
metadata.Source = source metadata.Source = source
metadata.SourceIP = parseSourceIP(conn)
return &SocketAdapter{ return &SocketAdapter{
conn: conn, conn: conn,

View file

@ -61,3 +61,10 @@ func parseHTTPAddr(request *http.Request) *C.Metadata {
return metadata return metadata
} }
func parseSourceIP(conn net.Conn) *net.IP {
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
return &addr.IP
}
return nil
}

View file

@ -338,7 +338,9 @@ func parseRules(cfg *rawConfig) ([]C.Rule, error) {
case "GEOIP": case "GEOIP":
rules = append(rules, R.NewGEOIP(payload, target)) rules = append(rules, R.NewGEOIP(payload, target))
case "IP-CIDR", "IP-CIDR6": case "IP-CIDR", "IP-CIDR6":
rules = append(rules, R.NewIPCIDR(payload, target)) rules = append(rules, R.NewIPCIDR(payload, target, false))
case "SOURCE-IP-CIDR":
rules = append(rules, R.NewIPCIDR(payload, target, true))
case "MATCH": case "MATCH":
fallthrough fallthrough
case "FINAL": case "FINAL":

View file

@ -33,6 +33,7 @@ type SourceType int
type Metadata struct { type Metadata struct {
NetWork NetWork NetWork NetWork
Source SourceType Source SourceType
SourceIP *net.IP
AddrType int AddrType int
Host string Host string
IP *net.IP IP *net.IP

View file

@ -7,6 +7,7 @@ const (
DomainKeyword DomainKeyword
GEOIP GEOIP
IPCIDR IPCIDR
SourceIPCIDR
FINAL FINAL
) )
@ -24,6 +25,8 @@ func (rt RuleType) String() string {
return "GEOIP" return "GEOIP"
case IPCIDR: case IPCIDR:
return "IPCIDR" return "IPCIDR"
case SourceIPCIDR:
return "SourceIPCIDR"
case FINAL: case FINAL:
return "FINAL" return "FINAL"
default: default:

View file

@ -9,18 +9,22 @@ import (
type IPCIDR struct { type IPCIDR struct {
ipnet *net.IPNet ipnet *net.IPNet
adapter string adapter string
isSourceIP bool
} }
func (i *IPCIDR) RuleType() C.RuleType { func (i *IPCIDR) RuleType() C.RuleType {
if i.isSourceIP {
return C.SourceIPCIDR
}
return C.IPCIDR return C.IPCIDR
} }
func (i *IPCIDR) IsMatch(metadata *C.Metadata) bool { func (i *IPCIDR) IsMatch(metadata *C.Metadata) bool {
if metadata.IP == nil { ip := metadata.IP
return false if i.isSourceIP {
ip = metadata.SourceIP
} }
return i.ipnet.Contains(*ip)
return i.ipnet.Contains(*metadata.IP)
} }
func (i *IPCIDR) Adapter() string { func (i *IPCIDR) Adapter() string {
@ -31,12 +35,13 @@ func (i *IPCIDR) Payload() string {
return i.ipnet.String() return i.ipnet.String()
} }
func NewIPCIDR(s string, adapter string) *IPCIDR { func NewIPCIDR(s string, adapter string, isSourceIP bool) *IPCIDR {
_, ipnet, err := net.ParseCIDR(s) _, ipnet, err := net.ParseCIDR(s)
if err != nil { if err != nil {
} }
return &IPCIDR{ return &IPCIDR{
ipnet: ipnet, ipnet: ipnet,
adapter: adapter, adapter: adapter,
isSourceIP: isSourceIP,
} }
} }

View file

@ -141,7 +141,7 @@ func (t *Tunnel) handleConn(localConn C.ServerAdapter) {
remoConn, err := proxy.Generator(metadata) remoConn, err := proxy.Generator(metadata)
if err != nil { if err != nil {
log.Warnln("Proxy[%s] connect [%s] error: %s", proxy.Name(), metadata.String(), err.Error()) log.Warnln("Proxy[%s] connect [%s --> %s] error: %s", proxy.Name(), metadata.SourceIP.String(), metadata.String(), err.Error())
return return
} }
defer remoConn.Close() defer remoConn.Close()
@ -174,12 +174,12 @@ func (t *Tunnel) match(metadata *C.Metadata) (C.Proxy, error) {
if rule.IsMatch(metadata) { if rule.IsMatch(metadata) {
if a, ok := t.proxies[rule.Adapter()]; ok { if a, ok := t.proxies[rule.Adapter()]; ok {
log.Infoln("%v match %s using %s", metadata.String(), rule.RuleType().String(), rule.Adapter()) log.Infoln("%s --> %v match %s using %s", metadata.SourceIP.String(), metadata.String(), rule.RuleType().String(), rule.Adapter())
return a, nil return a, nil
} }
} }
} }
log.Infoln("%v doesn't match any rule using DIRECT", metadata.String()) log.Infoln("%s --> %v doesn't match any rule using DIRECT", metadata.SourceIP.String(), metadata.String())
return t.proxies["DIRECT"], nil return t.proxies["DIRECT"], nil
} }