feature: MITM
This commit is contained in:
@ -35,6 +35,7 @@ import (
|
||||
L "github.com/Dreamacro/clash/listener"
|
||||
LC "github.com/Dreamacro/clash/listener/config"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
rewrites "github.com/Dreamacro/clash/rewrite"
|
||||
R "github.com/Dreamacro/clash/rules"
|
||||
RP "github.com/Dreamacro/clash/rules/provider"
|
||||
T "github.com/Dreamacro/clash/tunnel"
|
||||
@ -79,6 +80,7 @@ type Inbound struct {
|
||||
BindAddress string `json:"bind-address"`
|
||||
InboundTfo bool `json:"inbound-tfo"`
|
||||
InboundMPTCP bool `json:"inbound-mptcp"`
|
||||
MitmPort int `json:"mitm-port"`
|
||||
}
|
||||
|
||||
// Controller config
|
||||
@ -152,6 +154,12 @@ type Sniffer struct {
|
||||
ParsePureIp bool
|
||||
}
|
||||
|
||||
// Mitm config
|
||||
type Mitm struct {
|
||||
Port int `yaml:"port" json:"port"`
|
||||
Rules C.RewriteRule `yaml:"rules" json:"rules"`
|
||||
}
|
||||
|
||||
// Experimental config
|
||||
type Experimental struct {
|
||||
Fingerprints []string `yaml:"fingerprints"`
|
||||
@ -161,6 +169,7 @@ type Experimental struct {
|
||||
type Config struct {
|
||||
General *General
|
||||
IPTables *IPTables
|
||||
Mitm *Mitm
|
||||
NTP *NTP
|
||||
DNS *DNS
|
||||
Experimental *Experimental
|
||||
@ -253,12 +262,18 @@ type RawTuicServer struct {
|
||||
CWND int `yaml:"cwnd" json:"cwnd,omitempty"`
|
||||
}
|
||||
|
||||
type RawMitm struct {
|
||||
Port int `yaml:"port" json:"port"`
|
||||
Rules []string `yaml:"rules" json:"rules"`
|
||||
}
|
||||
|
||||
type RawConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
SocksPort int `yaml:"socks-port"`
|
||||
RedirPort int `yaml:"redir-port"`
|
||||
TProxyPort int `yaml:"tproxy-port"`
|
||||
MixedPort int `yaml:"mixed-port"`
|
||||
MitmPort int `yaml:"mitm-port"`
|
||||
ShadowSocksConfig string `yaml:"ss-config"`
|
||||
VmessConfig string `yaml:"vmess-config"`
|
||||
InboundTfo bool `yaml:"inbound-tfo"`
|
||||
@ -294,6 +309,7 @@ type RawConfig struct {
|
||||
TuicServer RawTuicServer `yaml:"tuic-server"`
|
||||
EBpf EBpf `yaml:"ebpf"`
|
||||
IPTables IPTables `yaml:"iptables"`
|
||||
MITM RawMitm `yaml:"mitm"`
|
||||
Experimental Experimental `yaml:"experimental"`
|
||||
Profile Profile `yaml:"profile"`
|
||||
GeoXUrl GeoXUrl `yaml:"geox-url"`
|
||||
@ -438,6 +454,10 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
||||
ParsePureIp: true,
|
||||
OverrideDest: true,
|
||||
},
|
||||
MITM: RawMitm{
|
||||
Port: 0,
|
||||
Rules: []string{},
|
||||
},
|
||||
Profile: Profile{
|
||||
StoreSelected: true,
|
||||
},
|
||||
@ -532,6 +552,12 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mitm, err := parseMitm(rawCfg.MITM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Mitm = mitm
|
||||
|
||||
config.Users = parseAuthentication(rawCfg.Authentication)
|
||||
|
||||
config.Tunnels = rawCfg.Tunnels
|
||||
@ -582,6 +608,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||
RedirPort: cfg.RedirPort,
|
||||
TProxyPort: cfg.TProxyPort,
|
||||
MixedPort: cfg.MixedPort,
|
||||
MitmPort: cfg.MitmPort,
|
||||
ShadowSocksConfig: cfg.ShadowSocksConfig,
|
||||
VmessConfig: cfg.VmessConfig,
|
||||
AllowLan: cfg.AllowLan,
|
||||
@ -629,6 +656,11 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
proxies["PASS"] = adapter.NewProxy(outbound.NewPass())
|
||||
proxyList = append(proxyList, "DIRECT", "REJECT")
|
||||
|
||||
if cfg.MITM.Port != 0 {
|
||||
proxies["MITM"] = adapter.NewProxy(outbound.NewMitm(fmt.Sprintf("127.0.0.1:%d", cfg.MITM.Port)))
|
||||
proxyList = append(proxyList, "MITM")
|
||||
}
|
||||
|
||||
// parse proxy
|
||||
for idx, mapping := range proxiesConfig {
|
||||
proxy, err := adapter.ParseProxy(mapping)
|
||||
@ -909,6 +941,14 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie[resolver.HostValue], error) {
|
||||
_ = tree.Insert(domain, value)
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.MITM.Port != 0 {
|
||||
value, _ := resolver.NewHostValue("8.8.9.9")
|
||||
if err := tree.Insert("mitm.clash", value); err != nil {
|
||||
log.Errorln("insert mitm.clash to host error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
tree.Optimize()
|
||||
|
||||
return tree, nil
|
||||
@ -1457,3 +1497,28 @@ func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
|
||||
|
||||
return sniffer, nil
|
||||
}
|
||||
|
||||
func parseMitm(rawMitm RawMitm) (*Mitm, error) {
|
||||
var (
|
||||
req []C.Rewrite
|
||||
res []C.Rewrite
|
||||
)
|
||||
|
||||
for _, line := range rawMitm.Rules {
|
||||
rule, err := rewrites.ParseRewrite(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse rewrite rule failure: %w", err)
|
||||
}
|
||||
|
||||
if rule.RuleType() == C.MitmResponseHeader || rule.RuleType() == C.MitmResponseBody {
|
||||
res = append(res, rule)
|
||||
} else {
|
||||
req = append(req, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return &Mitm{
|
||||
Port: rawMitm.Port,
|
||||
Rules: rewrites.NewRewriteRules(req, res),
|
||||
}, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user