feat: IN-TYPE rule support
eg. IN-TYPE,SOCKS/REDIR/INNER,Proxy support list: HTTP HTTPS SOCKS SOCKS4 SOCKS5 REDIR TPROXY TUN INNER
This commit is contained in:
parent
fa70694e4d
commit
ba7e0887bd
8 changed files with 114 additions and 7 deletions
|
@ -11,7 +11,7 @@ import (
|
|||
// NewHTTPS receive CONNECT request and return ConnContext
|
||||
func NewHTTPS(request *http.Request, conn net.Conn) *context.ConnContext {
|
||||
metadata := parseHTTPAddr(request)
|
||||
metadata.Type = C.HTTPCONNECT
|
||||
metadata.Type = C.HTTPS
|
||||
if ip, port, err := parseAddr(conn.RemoteAddr().String()); err == nil {
|
||||
metadata.SrcIP = ip
|
||||
metadata.SrcPort = port
|
||||
|
|
|
@ -19,7 +19,7 @@ const (
|
|||
ALLNet
|
||||
|
||||
HTTP Type = iota
|
||||
HTTPCONNECT
|
||||
HTTPS
|
||||
SOCKS4
|
||||
SOCKS5
|
||||
REDIR
|
||||
|
@ -49,8 +49,8 @@ func (t Type) String() string {
|
|||
switch t {
|
||||
case HTTP:
|
||||
return "HTTP"
|
||||
case HTTPCONNECT:
|
||||
return "HTTP Connect"
|
||||
case HTTPS:
|
||||
return "HTTPS"
|
||||
case SOCKS4:
|
||||
return "Socks4"
|
||||
case SOCKS5:
|
||||
|
@ -68,6 +68,31 @@ func (t Type) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func ParseType(t string) (*Type, error) {
|
||||
var res Type
|
||||
switch t {
|
||||
case "HTTP":
|
||||
res = HTTP
|
||||
case "HTTPS":
|
||||
res = HTTPS
|
||||
case "SOCKS4":
|
||||
res = SOCKS4
|
||||
case "SOCKS5":
|
||||
res = SOCKS5
|
||||
case "REDIR":
|
||||
res = REDIR
|
||||
case "TPROXY":
|
||||
res = TPROXY
|
||||
case "TUN":
|
||||
res = TUN
|
||||
case "INNER":
|
||||
res = INNER
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown type: %s", t)
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (t Type) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(t.String())
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ const (
|
|||
RuleSet
|
||||
Network
|
||||
Uid
|
||||
INTYPE
|
||||
MATCH
|
||||
AND
|
||||
OR
|
||||
|
@ -56,6 +57,8 @@ func (rt RuleType) String() string {
|
|||
return "Network"
|
||||
case Uid:
|
||||
return "Uid"
|
||||
case INTYPE:
|
||||
return "InType"
|
||||
case AND:
|
||||
return "AND"
|
||||
case OR:
|
||||
|
|
|
@ -20,7 +20,7 @@ type Rule struct {
|
|||
Type string `json:"type"`
|
||||
Payload string `json:"payload"`
|
||||
Proxy string `json:"proxy"`
|
||||
Size int `json:"Size"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
func getRules(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
74
rule/common/in_type.go
Normal file
74
rule/common/in_type.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type InType struct {
|
||||
*Base
|
||||
types []C.Type
|
||||
adapter string
|
||||
payload string
|
||||
}
|
||||
|
||||
func (u *InType) Match(metadata *C.Metadata) bool {
|
||||
for _, tp := range u.types {
|
||||
if metadata.Type == tp {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *InType) RuleType() C.RuleType {
|
||||
return C.INTYPE
|
||||
}
|
||||
|
||||
func (u *InType) Adapter() string {
|
||||
return u.adapter
|
||||
}
|
||||
|
||||
func (u *InType) Payload() string {
|
||||
return u.payload
|
||||
}
|
||||
|
||||
func NewInType(iTypes, adapter string) (*InType, error) {
|
||||
types := strings.Split(iTypes, "/")
|
||||
if len(types) == 0 {
|
||||
return nil, fmt.Errorf("in type could be empty")
|
||||
}
|
||||
|
||||
tps, err := parseInTypes(types)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InType{
|
||||
Base: &Base{},
|
||||
types: tps,
|
||||
adapter: adapter,
|
||||
payload: strings.ToUpper(iTypes),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseInTypes(tps []string) (res []C.Type, err error) {
|
||||
for _, tp := range tps {
|
||||
utp := strings.ToUpper(tp)
|
||||
var r *C.Type
|
||||
if utp == "SOCKS" {
|
||||
r, _ = C.ParseType("SOCKS4")
|
||||
res = append(res, *r)
|
||||
r, _ = C.ParseType("SOCKS5")
|
||||
res = append(res, *r)
|
||||
} else {
|
||||
r, err = C.ParseType(utp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = append(res, *r)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
|
@ -104,6 +104,8 @@ func parseRule(tp, payload string, params []string) (C.Rule, error) {
|
|||
case "RULE-SET":
|
||||
noResolve := RC.HasNoResolve(params)
|
||||
parsed, parseErr = provider.NewRuleSet(payload, "", noResolve)
|
||||
case "IN-TYPE":
|
||||
parsed, parseErr = RC.NewInType(payload, "")
|
||||
case "NOT":
|
||||
parsed, parseErr = NewNOT(payload, "")
|
||||
case "AND":
|
||||
|
|
|
@ -3,7 +3,6 @@ package rules
|
|||
import (
|
||||
"fmt"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
RC "github.com/Dreamacro/clash/rule/common"
|
||||
"github.com/Dreamacro/clash/rule/logic"
|
||||
RP "github.com/Dreamacro/clash/rule/provider"
|
||||
|
@ -47,8 +46,10 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
|||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||
parsed, parseErr = RC.NewUid(payload, target)
|
||||
} else {
|
||||
log.Warnln("uid rule not support this platform")
|
||||
parseErr = fmt.Errorf("uid rule not support this platform")
|
||||
}
|
||||
case "IN-TYPE":
|
||||
parsed, parseErr = RC.NewInType(payload, target)
|
||||
case "AND":
|
||||
parsed, parseErr = logic.NewAND(payload, target)
|
||||
case "OR":
|
||||
|
|
|
@ -84,6 +84,8 @@ func parseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
|||
parsed, parseErr = RC.NewProcess(payload, target, false)
|
||||
case "NETWORK":
|
||||
parsed, parseErr = RC.NewNetworkType(payload, target)
|
||||
case "IN-TYPE":
|
||||
parsed, parseErr = RC.NewInType(payload, target)
|
||||
default:
|
||||
parseErr = fmt.Errorf("unsupported rule type %s", tp)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue