mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 19:56:51 +08:00
Feature: SOURCE-IP-CIDR rule type (#96)
This commit is contained in:
parent
4ae154494c
commit
d292743981
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -33,6 +33,7 @@ type SourceType int
|
|||
type Metadata struct {
|
||||
NetWork NetWork
|
||||
Source SourceType
|
||||
SourceIP *net.IP
|
||||
AddrType int
|
||||
Host string
|
||||
IP *net.IP
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -7,20 +7,24 @@ import (
|
|||
)
|
||||
|
||||
type IPCIDR struct {
|
||||
ipnet *net.IPNet
|
||||
adapter string
|
||||
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,
|
||||
ipnet: ipnet,
|
||||
adapter: adapter,
|
||||
isSourceIP: isSourceIP,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user