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-SUFFIX,ad.com,REJECT
- IP-CIDR,127.0.0.0/8,DIRECT
- SOURCE-IP-CIDR,192.168.1.201/32,DIRECT
- GEOIP,CN,DIRECT
# FINAL would remove after prerelease
# 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
func NewHTTP(request *http.Request, conn net.Conn) *HTTPAdapter {
metadata := parseHTTPAddr(request)
metadata.SourceIP = parseSourceIP(conn)
return &HTTPAdapter{
metadata: parseHTTPAddr(request),
metadata: metadata,
R: request,
conn: conn,
}

View file

@ -7,8 +7,10 @@ import (
// NewHTTPS is HTTPAdapter generator
func NewHTTPS(request *http.Request, conn net.Conn) *SocketAdapter {
metadata := parseHTTPAddr(request)
metadata.SourceIP = parseSourceIP(conn)
return &SocketAdapter{
metadata: parseHTTPAddr(request),
metadata: metadata,
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 {
metadata := parseSocksAddr(target)
metadata.Source = source
metadata.SourceIP = parseSourceIP(conn)
return &SocketAdapter{
conn: conn,

View file

@ -61,3 +61,10 @@ func parseHTTPAddr(request *http.Request) *C.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":
rules = append(rules, R.NewGEOIP(payload, target))
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":
fallthrough
case "FINAL":

View file

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

View file

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

View file

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

View file

@ -141,7 +141,7 @@ func (t *Tunnel) handleConn(localConn C.ServerAdapter) {
remoConn, err := proxy.Generator(metadata)
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
}
defer remoConn.Close()
@ -174,12 +174,12 @@ func (t *Tunnel) match(metadata *C.Metadata) (C.Proxy, error) {
if rule.IsMatch(metadata) {
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
}
}
}
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
}