diff --git a/README.md b/README.md index 037ef0a7..c43e596f 100644 --- a/README.md +++ b/README.md @@ -223,19 +223,6 @@ proxies: servername: example.com # AKA SNI # flow: xtls-rprx-direct # xtls-rprx-origin # enable XTLS # skip-cert-verify: true - - - name: "vless-ws" - type: vless - server: server - port: 443 - uuid: uuid - udp: true - network: ws - servername: example.com # priority over wss host - # skip-cert-verify: true - ws-path: /path - ws-headers: - Host: example.com ``` ### IPTABLES auto-configuration @@ -249,9 +236,8 @@ tproxy-port: 9898 tun: enable: false ``` -Create user given name `clash`. -Run Clash by user `clash` as a daemon. +Run Clash as a daemon. Create the systemd configuration file at /etc/systemd/system/clash.service: ``` @@ -261,10 +247,7 @@ After=network.target [Service] Type=simple -User=clash -Group=clash CapabilityBoundingSet=cap_net_admin -AmbientCapabilities=cap_net_admin Restart=always ExecStart=/usr/local/bin/clash -d /etc/clash diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 211db5e0..09254c58 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -11,6 +11,7 @@ import ( func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) { opt := &option{ interfaceName: DefaultInterface.Load(), + routingMark: int(DefaultRoutingMark.Load()), } for _, o := range DefaultOptions { @@ -58,6 +59,7 @@ func DialContext(ctx context.Context, network, address string, options ...Option func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) { cfg := &option{ interfaceName: DefaultInterface.Load(), + routingMark: int(DefaultRoutingMark.Load()), } for _, o := range DefaultOptions { diff --git a/component/dialer/options.go b/component/dialer/options.go index b3cca810..2d884094 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -3,8 +3,9 @@ package dialer import "go.uber.org/atomic" var ( - DefaultOptions []Option - DefaultInterface = atomic.NewString("") + DefaultOptions []Option + DefaultInterface = atomic.NewString("") + DefaultRoutingMark = atomic.NewInt32(0) ) type option struct { diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 7f94daae..02c4645e 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -287,6 +287,7 @@ func updateIPTables(dns *config.DNS, general *config.General) { tproxy.CleanUpTProxyLinuxIPTables() + dialer.DefaultRoutingMark.Store(2158) err = tproxy.SetTProxyLinuxIPTables(general.Interface, general.TProxyPort, dnsPort) if err != nil { diff --git a/listener/tproxy/tproxy_linux_iptables.go b/listener/tproxy/tproxy_linux_iptables.go index 09650837..96e26387 100644 --- a/listener/tproxy/tproxy_linux_iptables.go +++ b/listener/tproxy/tproxy_linux_iptables.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" "os/exec" - U "os/user" "runtime" "strings" + "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/log" ) @@ -20,7 +20,6 @@ var ( const ( PROXY_FWMARK = "0x2d0" PROXY_ROUTE_TABLE = "0x2d0" - USERNAME = "clash" ) func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error { @@ -29,17 +28,10 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error { return fmt.Errorf("current operations system [%s] are not support iptables or command iptables does not exist", runtime.GOOS) } - user, err := U.Lookup(USERNAME) - if err != nil { - return fmt.Errorf("the user \" %s\" does not exist, please create it", USERNAME) - } - if ifname == "" { return errors.New("the 'interface-name' can not be empty") } - ownerUid := user.Uid - interfaceName = ifname tproxyPort = tport dnsPort = dport @@ -84,7 +76,7 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error { // set output execCmd("iptables -t mangle -N clash_output") execCmd("iptables -t mangle -F clash_output") - execCmd(fmt.Sprintf("iptables -t mangle -A clash_output -m owner --uid-owner %s -j RETURN", ownerUid)) + execCmd(fmt.Sprintf("iptables -t mangle -A clash_output -m mark --mark %#x -j RETURN", dialer.DefaultRoutingMark.Load())) execCmd("iptables -t mangle -A clash_output -p udp -m multiport --dports 53,123,137 -j ACCEPT") execCmd("iptables -t mangle -A clash_output -p tcp --dport 53 -j ACCEPT") execCmd("iptables -t mangle -A clash_output -m addrtype --dst-type LOCAL -j RETURN") @@ -97,7 +89,7 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error { // set dns output execCmd("iptables -t nat -N clash_dns_output") execCmd("iptables -t nat -F clash_dns_output") - execCmd(fmt.Sprintf("iptables -t nat -A clash_dns_output -m owner --uid-owner %s -j RETURN", ownerUid)) + execCmd(fmt.Sprintf("iptables -t nat -A clash_dns_output -m mark --mark %#x -j RETURN", dialer.DefaultRoutingMark.Load())) execCmd("iptables -t nat -A clash_dns_output -s 172.17.0.0/16 -j RETURN") execCmd(fmt.Sprintf("iptables -t nat -A clash_dns_output -p udp -j REDIRECT --to-ports %d", dnsPort)) execCmd(fmt.Sprintf("iptables -t nat -A clash_dns_output -p tcp -j REDIRECT --to-ports %d", dnsPort)) @@ -115,6 +107,8 @@ func CleanUpTProxyLinuxIPTables() { log.Warnln("Clean up tproxy linux iptables") + dialer.DefaultRoutingMark.Store(0) + if _, err := execCmd("iptables -t mangle -L clash_divert"); err != nil { return }