[skip ci]
# Conflicts: # .github/workflows/linter.yml # .github/workflows/release.yml # config/config.go # go.mod # go.sum # hub/executor/executor.go
This commit is contained in:
commit
a375b85fa0
14 changed files with 165 additions and 107 deletions
22
.github/workflows/linter.yml
vendored
Normal file
22
.github/workflows/linter.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: Linter
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get latest go version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g')
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: ${{ steps.version.outputs.go_version }}
|
||||||
|
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
|
@ -4,9 +4,7 @@ linters:
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- govet
|
- govet
|
||||||
# - gci
|
- gci
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
gci:
|
gci:
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -43,7 +43,7 @@ all:linux-amd64 linux-arm64\
|
||||||
windows-amd64 windows-arm64\
|
windows-amd64 windows-arm64\
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
$(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||||
|
|
||||||
darwin-amd64v3:
|
darwin-amd64v3:
|
||||||
GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||||
|
|
12
README.md
12
README.md
|
@ -212,16 +212,16 @@ proxies:
|
||||||
grpc-service-name: grpcname
|
grpc-service-name: grpcname
|
||||||
```
|
```
|
||||||
|
|
||||||
### IPTABLES auto-configuration
|
### IPTABLES configuration
|
||||||
Only work on Linux OS who support `iptables`, Clash will auto-configuration iptables for tproxy listener when `tproxy-port` value isn't zero.
|
Work on Linux OS who's supported `iptables`
|
||||||
|
|
||||||
If `TPROXY` is enabled, the `TUN` must be disabled.
|
|
||||||
```yaml
|
```yaml
|
||||||
# Enable the TPROXY listener
|
# Enable the TPROXY listener
|
||||||
tproxy-port: 9898
|
tproxy-port: 9898
|
||||||
# Disable the TUN listener
|
|
||||||
tun:
|
iptables:
|
||||||
enable: false
|
enable: true # default is false
|
||||||
|
inbound-interface: eth0 # detect the inbound interface, default is 'lo'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,12 @@ type Script struct {
|
||||||
ShortcutsCode map[string]string `yaml:"shortcuts" json:"shortcuts"`
|
ShortcutsCode map[string]string `yaml:"shortcuts" json:"shortcuts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPTables config
|
||||||
|
type IPTables struct {
|
||||||
|
Enable bool `yaml:"enable" json:"enable"`
|
||||||
|
InboundInterface string `yaml:"inbound-interface" json:"inbound-interface"`
|
||||||
|
}
|
||||||
|
|
||||||
// Experimental config
|
// Experimental config
|
||||||
type Experimental struct{}
|
type Experimental struct{}
|
||||||
|
|
||||||
|
@ -127,6 +133,7 @@ type Experimental struct{}
|
||||||
type Config struct {
|
type Config struct {
|
||||||
General *General
|
General *General
|
||||||
Tun *Tun
|
Tun *Tun
|
||||||
|
IPTables *IPTables
|
||||||
DNS *DNS
|
DNS *DNS
|
||||||
Experimental *Experimental
|
Experimental *Experimental
|
||||||
Hosts *trie.DomainTrie
|
Hosts *trie.DomainTrie
|
||||||
|
@ -196,6 +203,7 @@ type RawConfig struct {
|
||||||
Hosts map[string]string `yaml:"hosts"`
|
Hosts map[string]string `yaml:"hosts"`
|
||||||
DNS RawDNS `yaml:"dns"`
|
DNS RawDNS `yaml:"dns"`
|
||||||
Tun RawTun `yaml:"tun"`
|
Tun RawTun `yaml:"tun"`
|
||||||
|
IPTables IPTables `yaml:"iptables"`
|
||||||
Experimental Experimental `yaml:"experimental"`
|
Experimental Experimental `yaml:"experimental"`
|
||||||
Profile Profile `yaml:"profile"`
|
Profile Profile `yaml:"profile"`
|
||||||
Proxy []map[string]any `yaml:"proxies"`
|
Proxy []map[string]any `yaml:"proxies"`
|
||||||
|
@ -234,9 +242,13 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
||||||
Enable: false,
|
Enable: false,
|
||||||
Device: "",
|
Device: "",
|
||||||
Stack: C.TunGvisor,
|
Stack: C.TunGvisor,
|
||||||
DNSHijack: []string{"198.18.0.2:53"}, // default hijack all dns query
|
DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query
|
||||||
AutoRoute: true,
|
AutoRoute: true,
|
||||||
},
|
},
|
||||||
|
IPTables: IPTables{
|
||||||
|
Enable: false,
|
||||||
|
InboundInterface: "lo",
|
||||||
|
},
|
||||||
DNS: RawDNS{
|
DNS: RawDNS{
|
||||||
Enable: false,
|
Enable: false,
|
||||||
UseHosts: true,
|
UseHosts: true,
|
||||||
|
@ -255,8 +267,6 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
||||||
"1.0.0.1",
|
"1.0.0.1",
|
||||||
},
|
},
|
||||||
NameServer: []string{
|
NameServer: []string{
|
||||||
"223.5.5.5",
|
|
||||||
"119.29.29.29",
|
|
||||||
"https://doh.pub/dns-query",
|
"https://doh.pub/dns-query",
|
||||||
"tls://223.5.5.5:853",
|
"tls://223.5.5.5:853",
|
||||||
},
|
},
|
||||||
|
@ -288,6 +298,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
config.Experimental = &rawCfg.Experimental
|
config.Experimental = &rawCfg.Experimental
|
||||||
config.Profile = &rawCfg.Profile
|
config.Profile = &rawCfg.Profile
|
||||||
|
config.IPTables = &rawCfg.IPTables
|
||||||
|
|
||||||
general, err := parseGeneral(rawCfg)
|
general, err := parseGeneral(rawCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -630,7 +641,7 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie, error) {
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return nil, fmt.Errorf("%s is not a valid IP", ipStr)
|
return nil, fmt.Errorf("%s is not a valid IP", ipStr)
|
||||||
}
|
}
|
||||||
tree.Insert(domain, ip)
|
_ = tree.Insert(domain, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +666,7 @@ func hostWithDefaultPort(host string, defPort string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNameServer(servers []string) ([]dns.NameServer, error) {
|
func parseNameServer(servers []string) ([]dns.NameServer, error) {
|
||||||
nameservers := []dns.NameServer{}
|
var nameservers []dns.NameServer
|
||||||
|
|
||||||
for idx, server := range servers {
|
for idx, server := range servers {
|
||||||
// parse without scheme .e.g 8.8.8.8:53
|
// parse without scheme .e.g 8.8.8.8:53
|
||||||
|
@ -727,7 +738,7 @@ func parseNameServerPolicy(nsPolicy map[string]string) (map[string]dns.NameServe
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) {
|
func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) {
|
||||||
ipNets := []*net.IPNet{}
|
var ipNets []*net.IPNet
|
||||||
|
|
||||||
for idx, ip := range ips {
|
for idx, ip := range ips {
|
||||||
_, ipnet, err := net.ParseCIDR(ip)
|
_, ipnet, err := net.ParseCIDR(ip)
|
||||||
|
@ -829,7 +840,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie, rules []C.Rule) (*DNS,
|
||||||
if len(cfg.FakeIPFilter) != 0 {
|
if len(cfg.FakeIPFilter) != 0 {
|
||||||
host = trie.New()
|
host = trie.New()
|
||||||
for _, domain := range cfg.FakeIPFilter {
|
for _, domain := range cfg.FakeIPFilter {
|
||||||
host.Insert(domain, true)
|
_ = host.Insert(domain, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -26,10 +26,10 @@ require (
|
||||||
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5
|
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5
|
||||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
|
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6
|
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
golang.zx2c4.com/wireguard/windows v0.5.4-0.20220317000008-6432784c2469
|
||||||
google.golang.org/protobuf v1.27.1
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gvisor.dev/gvisor v0.0.0-20220315202956-f1399ecf1672
|
gvisor.dev/gvisor v0.0.0-20220319025644-e785bfc153f5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -54,7 +54,6 @@ require (
|
||||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 => github.com/MetaCubeX/wintun-go v0.0.0-20220319102620-bbc5e6b2015e
|
replace golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 => github.com/MetaCubeX/wintun-go v0.0.0-20220319102620-bbc5e6b2015e
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -341,8 +341,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 h1:kgBK1EGuTIYbwoKROmsoV0FQp08gnCcVa110A4Unqhk=
|
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 h1:kgBK1EGuTIYbwoKROmsoV0FQp08gnCcVa110A4Unqhk=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
|
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
golang.zx2c4.com/wireguard/windows v0.5.4-0.20220317000008-6432784c2469 h1:SEYkJAIuYAsSAPkCffOiYLtq5brBDSI+L0mRjSsvSTY=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
golang.zx2c4.com/wireguard/windows v0.5.4-0.20220317000008-6432784c2469/go.mod h1:1CeiatTZwcwSFA3cAtMm8CQoroviTldnxd7DOgM/vI4=
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||||
|
@ -385,8 +385,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
gvisor.dev/gvisor v0.0.0-20220315202956-f1399ecf1672 h1:aXIFpjZYl3zv2rQyr4rSit5Uq0k7BVXC8lJaDa4Cg7M=
|
gvisor.dev/gvisor v0.0.0-20220319025644-e785bfc153f5 h1:a3DiynlmTM9IGW+twgZSDhYNGcnxvU/+pbzrl1xMcJ4=
|
||||||
gvisor.dev/gvisor v0.0.0-20220315202956-f1399ecf1672/go.mod h1:V4WNP2Uwtx69eOhvLDSQ734EaTJTaBI3P8KgRAlROsg=
|
gvisor.dev/gvisor v0.0.0-20220319025644-e785bfc153f5/go.mod h1:tWwEcFvJavs154OdjFCw78axNrsDlz4Zh8jvPqwcpGI=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -2,15 +2,12 @@ package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Dreamacro/clash/listener/tun/ipstack/commons"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/listener/tproxy"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter"
|
"github.com/Dreamacro/clash/adapter"
|
||||||
"github.com/Dreamacro/clash/adapter/outboundgroup"
|
"github.com/Dreamacro/clash/adapter/outboundgroup"
|
||||||
"github.com/Dreamacro/clash/component/auth"
|
"github.com/Dreamacro/clash/component/auth"
|
||||||
|
@ -27,6 +24,7 @@ import (
|
||||||
"github.com/Dreamacro/clash/dns"
|
"github.com/Dreamacro/clash/dns"
|
||||||
P "github.com/Dreamacro/clash/listener"
|
P "github.com/Dreamacro/clash/listener"
|
||||||
authStore "github.com/Dreamacro/clash/listener/auth"
|
authStore "github.com/Dreamacro/clash/listener/auth"
|
||||||
|
"github.com/Dreamacro/clash/listener/tproxy"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
"github.com/Dreamacro/clash/tunnel"
|
"github.com/Dreamacro/clash/tunnel"
|
||||||
)
|
)
|
||||||
|
@ -79,8 +77,8 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||||
updateRules(cfg.Rules, cfg.RuleProviders)
|
updateRules(cfg.Rules, cfg.RuleProviders)
|
||||||
updateDNS(cfg.DNS, cfg.Tun)
|
updateDNS(cfg.DNS, cfg.Tun)
|
||||||
updateGeneral(cfg.General, force)
|
updateGeneral(cfg.General, force)
|
||||||
updateTun(cfg.Tun)
|
updateIPTables(cfg)
|
||||||
autoUpdateIPTables(cfg.DNS, cfg.General, cfg.Tun)
|
updateTun(cfg.Tun, cfg.DNS)
|
||||||
updateExperimental(cfg)
|
updateExperimental(cfg)
|
||||||
updateHosts(cfg.Hosts)
|
updateHosts(cfg.Hosts)
|
||||||
loadProvider(cfg.RuleProviders, cfg.Providers)
|
loadProvider(cfg.RuleProviders, cfg.Providers)
|
||||||
|
@ -211,8 +209,8 @@ func loadProvider(ruleProviders map[string]*provider.RuleProvider, proxyProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateTun(tun *config.Tun) {
|
func updateTun(tun *config.Tun, dns *config.DNS) {
|
||||||
P.ReCreateTun(tun, tunnel.TCPIn(), tunnel.UDPIn())
|
P.ReCreateTun(tun, dns, tunnel.TCPIn(), tunnel.UDPIn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateGeneral(general *config.General, force bool) {
|
func updateGeneral(general *config.General, force bool) {
|
||||||
|
@ -301,60 +299,67 @@ func patchSelectGroup(proxies map[string]C.Proxy) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoUpdateIPTables(dns *config.DNS, general *config.General, tun *config.Tun) {
|
func updateIPTables(cfg *config.Config) {
|
||||||
if runtime.GOOS != "linux" || general.TProxyPort == 0 {
|
tproxy.CleanupTProxyIPTables()
|
||||||
|
|
||||||
|
iptables := cfg.IPTables
|
||||||
|
if runtime.GOOS != "linux" || !iptables.Enable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("Setting iptables failed: %s", err.Error())
|
log.Errorln("[IPTABLES] setting iptables failed: %s", err.Error())
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !dns.Enable || dns.Listen == "" {
|
var (
|
||||||
|
inboundInterface = "lo"
|
||||||
|
tProxyPort = cfg.General.TProxyPort
|
||||||
|
dnsCfg = cfg.DNS
|
||||||
|
)
|
||||||
|
|
||||||
|
if tProxyPort == 0 {
|
||||||
|
err = fmt.Errorf("tproxy-port must be greater than zero")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dnsCfg.Enable {
|
||||||
err = fmt.Errorf("DNS server must be enable")
|
err = fmt.Errorf("DNS server must be enable")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tun.Enable {
|
_, dnsPortStr, err := net.SplitHostPort(dnsCfg.Listen)
|
||||||
err = fmt.Errorf("TUN device must be disabe")
|
if err != nil {
|
||||||
|
err = fmt.Errorf("DNS server must be correct")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = updateIPTables(dns, general)
|
dnsPort, err := strconv.ParseUint(dnsPortStr, 10, 16)
|
||||||
go commons.DefaultInterfaceChangeMonitor(func(_ string) {
|
if err != nil {
|
||||||
updateIPTables(dns, general)
|
err = fmt.Errorf("DNS server must be correct")
|
||||||
})
|
return
|
||||||
}
|
|
||||||
|
|
||||||
func updateIPTables(dns *config.DNS, general *config.General) error {
|
|
||||||
tproxy.CleanUpTProxyLinuxIPTables()
|
|
||||||
|
|
||||||
_, dnsPortStr, err := net.SplitHostPort(dns.Listen)
|
|
||||||
if dnsPortStr == "0" || dnsPortStr == "" || err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsPort, err := strconv.Atoi(dnsPortStr)
|
if iptables.InboundInterface != "" {
|
||||||
if err != nil {
|
inboundInterface = iptables.InboundInterface
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if dialer.DefaultRoutingMark.Load() == 0 {
|
if dialer.DefaultRoutingMark.Load() == 0 {
|
||||||
dialer.DefaultRoutingMark.Store(2158)
|
dialer.DefaultRoutingMark.Store(2158)
|
||||||
}
|
}
|
||||||
if general.AutoIptables {
|
|
||||||
err = tproxy.SetTProxyLinuxIPTables(dialer.DefaultInterface.Load(), general.TProxyPort, dnsPort)
|
err = tproxy.SetTProxyIPTables(inboundInterface, uint16(tProxyPort), uint16(dnsPort))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
log.Infoln("[IPTABLES] Setting iptables completed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Cleanup() {
|
func Cleanup() {
|
||||||
P.Cleanup()
|
P.Cleanup()
|
||||||
if runtime.GOOS == "linux" {
|
tproxy.CleanupTProxyIPTables()
|
||||||
tproxy.CleanUpTProxyLinuxIPTables()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,7 +310,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
|
||||||
log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address())
|
log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
func ReCreateTun(tunConf *config.Tun, dnsCfg *config.DNS, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
tunMux.Lock()
|
tunMux.Lock()
|
||||||
defer tunMux.Unlock()
|
defer tunMux.Unlock()
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
|
||||||
if !tunConf.Enable {
|
if !tunConf.Enable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tunStackListener, err = tun.New(tunConf, tcpIn, udpIn)
|
tunStackListener, err = tun.New(tunConf, dnsCfg, tcpIn, udpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("Failed to start TUN interface: %s", err.Error())
|
log.Warnln("Failed to start TUN interface: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dnsPort = 0
|
dnsPort uint16
|
||||||
tProxyPort = 0
|
tProxyPort uint16
|
||||||
interfaceName = ""
|
interfaceName string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -21,7 +21,7 @@ const (
|
||||||
PROXY_ROUTE_TABLE = "0x2d0"
|
PROXY_ROUTE_TABLE = "0x2d0"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error {
|
func SetTProxyIPTables(ifname string, tport uint16, dport uint16) error {
|
||||||
var err error
|
var err error
|
||||||
if err = execCmd("iptables -V"); err != nil {
|
if err = execCmd("iptables -V"); err != nil {
|
||||||
return fmt.Errorf("current operations system [%s] are not support iptables or command iptables does not exist", runtime.GOOS)
|
return fmt.Errorf("current operations system [%s] are not support iptables or command iptables does not exist", runtime.GOOS)
|
||||||
|
@ -40,11 +40,13 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error {
|
||||||
execCmd(fmt.Sprintf("ip -f inet route add local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
execCmd(fmt.Sprintf("ip -f inet route add local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
||||||
|
|
||||||
// set FORWARD
|
// set FORWARD
|
||||||
|
if interfaceName != "lo" {
|
||||||
execCmd("sysctl -w net.ipv4.ip_forward=1")
|
execCmd("sysctl -w net.ipv4.ip_forward=1")
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -o %s -j ACCEPT", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -o %s -j ACCEPT", interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -A FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
|
}
|
||||||
|
|
||||||
// set clash divert
|
// set clash divert
|
||||||
execCmd("iptables -t mangle -N clash_divert")
|
execCmd("iptables -t mangle -N clash_divert")
|
||||||
|
@ -70,7 +72,9 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error {
|
||||||
execCmd(fmt.Sprintf("iptables -t nat -I PREROUTING ! -s 172.17.0.0/16 ! -d 127.0.0.0/8 -p udp --dport 53 -j REDIRECT --to %d", dnsPort))
|
execCmd(fmt.Sprintf("iptables -t nat -I PREROUTING ! -s 172.17.0.0/16 ! -d 127.0.0.0/8 -p udp --dport 53 -j REDIRECT --to %d", dnsPort))
|
||||||
|
|
||||||
// set post routing
|
// set post routing
|
||||||
|
if interfaceName != "lo" {
|
||||||
execCmd(fmt.Sprintf("iptables -t nat -A POSTROUTING -o %s -m addrtype ! --src-type LOCAL -j MASQUERADE", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t nat -A POSTROUTING -o %s -m addrtype ! --src-type LOCAL -j MASQUERADE", interfaceName))
|
||||||
|
}
|
||||||
|
|
||||||
// set output
|
// set output
|
||||||
execCmd("iptables -t mangle -N clash_output")
|
execCmd("iptables -t mangle -N clash_output")
|
||||||
|
@ -95,16 +99,15 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error {
|
||||||
execCmd("iptables -t nat -I OUTPUT -p tcp --dport 53 -j clash_dns_output")
|
execCmd("iptables -t nat -I OUTPUT -p tcp --dport 53 -j clash_dns_output")
|
||||||
execCmd("iptables -t nat -I OUTPUT -p udp --dport 53 -j clash_dns_output")
|
execCmd("iptables -t nat -I OUTPUT -p udp --dport 53 -j clash_dns_output")
|
||||||
|
|
||||||
log.Infoln("[TPROXY] Setting iptables completed")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanUpTProxyLinuxIPTables() {
|
func CleanupTProxyIPTables() {
|
||||||
if interfaceName == "" || tProxyPort == 0 || dnsPort == 0 {
|
if runtime.GOOS != "linux" || interfaceName == "" || tProxyPort == 0 || dnsPort == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warnln("Clean up tproxy linux iptables")
|
log.Warnln("Cleanup tproxy linux iptables")
|
||||||
|
|
||||||
if int(dialer.DefaultRoutingMark.Load()) == 2158 {
|
if int(dialer.DefaultRoutingMark.Load()) == 2158 {
|
||||||
dialer.DefaultRoutingMark.Store(0)
|
dialer.DefaultRoutingMark.Store(0)
|
||||||
|
@ -119,10 +122,12 @@ func CleanUpTProxyLinuxIPTables() {
|
||||||
execCmd(fmt.Sprintf("ip -f inet route del local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
execCmd(fmt.Sprintf("ip -f inet route del local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
||||||
|
|
||||||
// clean FORWARD
|
// clean FORWARD
|
||||||
|
if interfaceName != "lo" {
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -j ACCEPT", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -j ACCEPT", interfaceName))
|
||||||
|
}
|
||||||
|
|
||||||
// clean PREROUTING
|
// clean PREROUTING
|
||||||
execCmd(fmt.Sprintf("iptables -t nat -D PREROUTING ! -s 172.17.0.0/16 ! -d 127.0.0.0/8 -p tcp --dport 53 -j REDIRECT --to %d", dnsPort))
|
execCmd(fmt.Sprintf("iptables -t nat -D PREROUTING ! -s 172.17.0.0/16 ! -d 127.0.0.0/8 -p tcp --dport 53 -j REDIRECT --to %d", dnsPort))
|
||||||
|
@ -130,7 +135,9 @@ func CleanUpTProxyLinuxIPTables() {
|
||||||
execCmd("iptables -t mangle -D PREROUTING -j clash_prerouting")
|
execCmd("iptables -t mangle -D PREROUTING -j clash_prerouting")
|
||||||
|
|
||||||
// clean POSTROUTING
|
// clean POSTROUTING
|
||||||
|
if interfaceName != "lo" {
|
||||||
execCmd(fmt.Sprintf("iptables -t nat -D POSTROUTING -o %s -m addrtype ! --src-type LOCAL -j MASQUERADE", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t nat -D POSTROUTING -o %s -m addrtype ! --src-type LOCAL -j MASQUERADE", interfaceName))
|
||||||
|
}
|
||||||
|
|
||||||
// clean OUTPUT
|
// clean OUTPUT
|
||||||
execCmd(fmt.Sprintf("iptables -t mangle -D OUTPUT -o %s -j clash_output", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t mangle -D OUTPUT -o %s -j clash_output", interfaceName))
|
||||||
|
@ -146,6 +153,10 @@ func CleanUpTProxyLinuxIPTables() {
|
||||||
execCmd("iptables -t mangle -X clash_output")
|
execCmd("iptables -t mangle -X clash_output")
|
||||||
execCmd("iptables -t nat -F clash_dns_output")
|
execCmd("iptables -t nat -F clash_dns_output")
|
||||||
execCmd("iptables -t nat -X clash_dns_output")
|
execCmd("iptables -t nat -X clash_dns_output")
|
||||||
|
|
||||||
|
interfaceName = ""
|
||||||
|
tProxyPort = 0
|
||||||
|
dnsPort = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func addLocalnetworkToChain(chain string) {
|
func addLocalnetworkToChain(chain string) {
|
||||||
|
@ -167,11 +178,11 @@ func addLocalnetworkToChain(chain string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func execCmd(cmdStr string) error {
|
func execCmd(cmdStr string) error {
|
||||||
log.Debugln("[TPROXY] %s", cmdStr)
|
log.Debugln("[IPTABLES] %s", cmdStr)
|
||||||
|
|
||||||
_, err := cmd.ExecCmd(cmdStr)
|
_, err := cmd.ExecCmd(cmdStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("[TPROXY] exec cmd: %v", err)
|
log.Warnln("[IPTABLES] exec cmd: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -5,6 +5,7 @@ package tun
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
"github.com/Dreamacro/clash/listener/tun/device"
|
"github.com/Dreamacro/clash/listener/tun/device"
|
||||||
|
@ -50,9 +51,18 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nt, err := tun.CreateTUN(t.name, forcedMTU) // forcedMTU do not work on wintun, need to be setting by other way
|
nt, err := tun.CreateTUN(t.name, forcedMTU) // forcedMTU do not work on wintun, need to be setting by other way
|
||||||
|
|
||||||
|
// retry if abnormal exit on Windows at last time
|
||||||
|
if err != nil && runtime.GOOS == "windows" &&
|
||||||
|
strings.HasSuffix(err.Error(), "file already exists.") {
|
||||||
|
|
||||||
|
nt, err = tun.CreateTUN(t.name, forcedMTU)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create tun: %w", err)
|
return nil, fmt.Errorf("create tun: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.nt = nt.(*tun.NativeTun)
|
t.nt = nt.(*tun.NativeTun)
|
||||||
|
|
||||||
tunMTU, err := nt.MTU()
|
tunMTU, err := nt.MTU()
|
||||||
|
|
|
@ -41,7 +41,9 @@ startOver:
|
||||||
var (
|
var (
|
||||||
luid = winipcfg.LUID(dev.(*tun.TUN).LUID())
|
luid = winipcfg.LUID(dev.(*tun.TUN).LUID())
|
||||||
ip = addr.Masked().Addr().Next()
|
ip = addr.Masked().Addr().Next()
|
||||||
|
gw = ip.Next()
|
||||||
addresses = []netip.Prefix{netip.PrefixFrom(ip, addr.Bits())}
|
addresses = []netip.Prefix{netip.PrefixFrom(ip, addr.Bits())}
|
||||||
|
dnsAddress = []netip.Addr{gw}
|
||||||
|
|
||||||
family4 = winipcfg.AddressFamily(windows.AF_INET)
|
family4 = winipcfg.AddressFamily(windows.AF_INET)
|
||||||
familyV6 = winipcfg.AddressFamily(windows.AF_INET6)
|
familyV6 = winipcfg.AddressFamily(windows.AF_INET6)
|
||||||
|
@ -123,7 +125,7 @@ startOver:
|
||||||
// add gateway
|
// add gateway
|
||||||
deduplicatedRoutes = append(deduplicatedRoutes, &winipcfg.RouteData{
|
deduplicatedRoutes = append(deduplicatedRoutes, &winipcfg.RouteData{
|
||||||
Destination: addr.Masked(),
|
Destination: addr.Masked(),
|
||||||
NextHop: addr.Masked().Addr().Next().Next(),
|
NextHop: gw,
|
||||||
Metric: 0,
|
Metric: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -193,12 +195,11 @@ startOver:
|
||||||
return fmt.Errorf("unable to set v6 metric and MTU: %w", err)
|
return fmt.Errorf("unable to set v6 metric and MTU: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsAdds := []netip.Addr{netip.MustParseAddr("198.18.0.2")}
|
err = luid.SetDNS(family4, dnsAddress, nil)
|
||||||
err = luid.SetDNS(family4, dnsAdds, nil)
|
|
||||||
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
|
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
|
||||||
goto startOver
|
goto startOver
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return fmt.Errorf("unable to set DNS %s %s: %w", "198.18.0.2", "nil", err)
|
return fmt.Errorf("unable to set DNS %s %s: %w", dnsAddress[0].String(), "nil", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wintunInterfaceName = dev.Name()
|
wintunInterfaceName = dev.Name()
|
||||||
|
|
|
@ -2,12 +2,6 @@ package tun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
|
||||||
"net/url"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
"github.com/Dreamacro/clash/common/cmd"
|
"github.com/Dreamacro/clash/common/cmd"
|
||||||
"github.com/Dreamacro/clash/component/process"
|
"github.com/Dreamacro/clash/component/process"
|
||||||
|
@ -21,12 +15,21 @@ import (
|
||||||
"github.com/Dreamacro/clash/listener/tun/ipstack/gvisor"
|
"github.com/Dreamacro/clash/listener/tun/ipstack/gvisor"
|
||||||
"github.com/Dreamacro/clash/listener/tun/ipstack/system"
|
"github.com/Dreamacro/clash/listener/tun/ipstack/system"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
"net/netip"
|
||||||
|
"net/url"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New TunAdapter
|
// New TunAdapter
|
||||||
func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
func New(tunConf *config.Tun, dnsConf *config.DNS, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
||||||
|
var tunAddressPrefix string
|
||||||
|
if dnsConf.FakeIPRange != nil {
|
||||||
|
tunAddressPrefix = dnsConf.FakeIPRange.IPNet().String()
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tunAddress, _ = netip.ParsePrefix("198.18.0.1/16")
|
tunAddress, _ = netip.ParsePrefix(tunAddressPrefix)
|
||||||
devName = tunConf.Device
|
devName = tunConf.Device
|
||||||
stackType = tunConf.Stack
|
stackType = tunConf.Stack
|
||||||
autoRoute = tunConf.AutoRoute
|
autoRoute = tunConf.AutoRoute
|
||||||
|
@ -42,21 +45,19 @@ func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.
|
||||||
devName = generateDeviceName()
|
devName = generateDeviceName()
|
||||||
}
|
}
|
||||||
|
|
||||||
//if !tunAddress.IsValid() || !tunAddress.Addr().Is4() {
|
if !tunAddress.IsValid() || !tunAddress.Addr().Is4() {
|
||||||
// tunAddress = netip.MustParsePrefix("198.18.0.1/16")
|
tunAddress = netip.MustParsePrefix("198.18.0.1/16")
|
||||||
//}
|
}
|
||||||
|
|
||||||
process.AppendLocalIPs(tunAddress.Masked().Addr().Next().AsSlice())
|
process.AppendLocalIPs(tunAddress.Masked().Addr().Next().AsSlice())
|
||||||
|
|
||||||
// open tun device
|
// open tun device
|
||||||
for i := 1; i < 3; i++ {
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
tunDevice, err = parseDevice(devName, uint32(mtu))
|
tunDevice, err = parseDevice(devName, uint32(mtu))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't open tun: %w", err)
|
return nil, fmt.Errorf("can't open tun: %w", err)
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
|
||||||
// new ip stack
|
// new ip stack
|
||||||
switch stackType {
|
switch stackType {
|
||||||
case C.TunGvisor:
|
case C.TunGvisor:
|
||||||
|
|
2
main.go
2
main.go
|
@ -48,7 +48,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
|
_, _ = maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
|
||||||
if version {
|
if version {
|
||||||
fmt.Printf("Clash Meta %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime)
|
fmt.Printf("Clash Meta %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue