mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 11:42:43 +08:00
chore: listeners support tun
This commit is contained in:
parent
5c410b8df4
commit
fd9c4cbfa5
|
@ -243,7 +243,7 @@ type RawTun struct {
|
|||
RedirectToTun []string `yaml:"-" json:"-"`
|
||||
|
||||
MTU uint32 `yaml:"mtu" json:"mtu,omitempty"`
|
||||
//Inet4Address []ListenPrefix `yaml:"inet4-address" json:"inet4_address,omitempty"`
|
||||
//Inet4Address []LC.ListenPrefix `yaml:"inet4-address" json:"inet4_address,omitempty"`
|
||||
Inet6Address []LC.ListenPrefix `yaml:"inet6-address" json:"inet6_address,omitempty"`
|
||||
StrictRoute bool `yaml:"strict-route" json:"strict_route,omitempty"`
|
||||
Inet4RouteAddress []LC.ListenPrefix `yaml:"inet4_route_address" json:"inet4_route_address,omitempty"`
|
||||
|
|
|
@ -740,3 +740,40 @@ listeners:
|
|||
network: [ tcp, udp ]
|
||||
target: target.com
|
||||
|
||||
- name: tun-in-1
|
||||
type: tun
|
||||
# rule: sub-rule
|
||||
stack: system # gvisor / lwip
|
||||
dns-hijack:
|
||||
- 0.0.0.0:53 # 需要劫持的 DNS
|
||||
# auto-detect-interface: false # 自动识别出口网卡
|
||||
# auto-route: false # 配置路由表
|
||||
# mtu: 9000 # 最大传输单元
|
||||
# strict_route: true # 将所有连接路由到tun来防止泄漏,但你的设备将无法其他设备被访问
|
||||
inet4_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由
|
||||
- 0.0.0.0/1
|
||||
- 128.0.0.0/1
|
||||
inet6_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由
|
||||
- "::/1"
|
||||
- "8000::/1"
|
||||
# endpoint_independent_nat: false # 启用独立于端点的 NAT
|
||||
# include_uid: # UID 规则仅在 Linux 下被支持,并且需要 auto_route
|
||||
# - 0
|
||||
# include_uid_range: # 限制被路由的的用户范围
|
||||
# - 1000-99999
|
||||
# exclude_uid: # 排除路由的的用户
|
||||
#- 1000
|
||||
# exclude_uid_range: # 排除路由的的用户范围
|
||||
# - 1000-99999
|
||||
|
||||
# Android 用户和应用规则仅在 Android 下被支持
|
||||
# 并且需要 auto_route
|
||||
|
||||
# include_android_user: # 限制被路由的 Android 用户
|
||||
# - 0
|
||||
# - 10
|
||||
# include_package: # 限制被路由的 Android 应用包名
|
||||
# - com.android.chrome
|
||||
# exclude_package: # 排除被路由的 Android 应用包名
|
||||
# - com.android.captiveportallogin
|
||||
|
||||
|
|
|
@ -58,6 +58,18 @@ func (p ListenPrefix) Build() netip.Prefix {
|
|||
return netip.Prefix(p)
|
||||
}
|
||||
|
||||
func StringSliceToListenPrefixSlice(ss []string) ([]ListenPrefix, error) {
|
||||
lps := make([]ListenPrefix, 0, len(ss))
|
||||
for _, s := range ss {
|
||||
prefix, err := netip.ParsePrefix(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lps = append(lps, ListenPrefix(prefix))
|
||||
}
|
||||
return lps, nil
|
||||
}
|
||||
|
||||
type Tun struct {
|
||||
Enable bool
|
||||
Device string
|
||||
|
|
|
@ -74,7 +74,7 @@ var _ C.InboundListener = (*Base)(nil)
|
|||
type BaseOption struct {
|
||||
NameStr string `inbound:"name"`
|
||||
Listen string `inbound:"listen,omitempty"`
|
||||
Port int `inbound:"port"`
|
||||
Port int `inbound:"port,omitempty"`
|
||||
SpecialRules string `inbound:"rule,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ type ShadowSocks struct {
|
|||
*Base
|
||||
config *ShadowSocksOption
|
||||
l C.MultiAddrListener
|
||||
ss LC.ShadowsocksServer
|
||||
}
|
||||
|
||||
func NewShadowSocks(options *ShadowSocksOption) (*ShadowSocks, error) {
|
||||
|
@ -31,8 +32,13 @@ func NewShadowSocks(options *ShadowSocksOption) (*ShadowSocks, error) {
|
|||
return &ShadowSocks{
|
||||
Base: base,
|
||||
config: options,
|
||||
ss: LC.ShadowsocksServer{
|
||||
Enable: true,
|
||||
Listen: base.RawAddress(),
|
||||
Password: options.Password,
|
||||
Cipher: options.Cipher,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
// Config implements constant.InboundListener
|
||||
|
@ -53,17 +59,7 @@ func (s *ShadowSocks) Address() string {
|
|||
// Listen implements constant.InboundListener
|
||||
func (s *ShadowSocks) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||
var err error
|
||||
s.l, err = sing_shadowsocks.New(
|
||||
LC.ShadowsocksServer{
|
||||
Enable: true,
|
||||
Listen: s.RawAddress(),
|
||||
Password: s.config.Password,
|
||||
Cipher: s.config.Cipher,
|
||||
},
|
||||
tcpIn,
|
||||
udpIn,
|
||||
s.Additions()...,
|
||||
)
|
||||
s.l, err = sing_shadowsocks.New(s.ss, tcpIn, udpIn, s.Additions()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ type Tuic struct {
|
|||
*Base
|
||||
config *TuicOption
|
||||
l *tuic.Listener
|
||||
ts LC.TuicServer
|
||||
}
|
||||
|
||||
func NewTuic(options *TuicOption) (*Tuic, error) {
|
||||
|
@ -37,8 +38,19 @@ func NewTuic(options *TuicOption) (*Tuic, error) {
|
|||
return &Tuic{
|
||||
Base: base,
|
||||
config: options,
|
||||
ts: LC.TuicServer{
|
||||
Enable: true,
|
||||
Listen: base.RawAddress(),
|
||||
Token: options.Token,
|
||||
Certificate: options.Certificate,
|
||||
PrivateKey: options.PrivateKey,
|
||||
CongestionController: options.CongestionController,
|
||||
MaxIdleTime: options.MaxIdleTime,
|
||||
AuthenticationTimeout: options.AuthenticationTimeout,
|
||||
ALPN: options.ALPN,
|
||||
MaxUdpRelayPacketSize: options.MaxUdpRelayPacketSize,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
// Config implements constant.InboundListener
|
||||
|
@ -59,23 +71,7 @@ func (t *Tuic) Address() string {
|
|||
// Listen implements constant.InboundListener
|
||||
func (t *Tuic) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||
var err error
|
||||
t.l, err = tuic.New(
|
||||
LC.TuicServer{
|
||||
Enable: true,
|
||||
Listen: t.RawAddress(),
|
||||
Token: t.config.Token,
|
||||
Certificate: t.config.Certificate,
|
||||
PrivateKey: t.config.PrivateKey,
|
||||
CongestionController: t.config.CongestionController,
|
||||
MaxIdleTime: t.config.MaxIdleTime,
|
||||
AuthenticationTimeout: t.config.AuthenticationTimeout,
|
||||
ALPN: t.config.ALPN,
|
||||
MaxUdpRelayPacketSize: t.config.MaxUdpRelayPacketSize,
|
||||
},
|
||||
tcpIn,
|
||||
udpIn,
|
||||
t.Additions()...,
|
||||
)
|
||||
t.l, err = tuic.New(t.ts, tcpIn, udpIn, t.Additions()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
139
listener/inbound/tun.go
Normal file
139
listener/inbound/tun.go
Normal file
|
@ -0,0 +1,139 @@
|
|||
package inbound
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
LC "github.com/Dreamacro/clash/listener/config"
|
||||
"github.com/Dreamacro/clash/listener/sing_tun"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
type TunOption struct {
|
||||
BaseOption
|
||||
Device string `inbound:"device,omitempty"`
|
||||
Stack string `inbound:"stack,omitempty"`
|
||||
DNSHijack []string `inbound:"dns-hijack,omitempty"`
|
||||
AutoRoute bool `inbound:"auto-route,omitempty"`
|
||||
AutoDetectInterface bool `inbound:"auto-detect-interface,omitempty"`
|
||||
|
||||
MTU uint32 `inbound:"mtu,omitempty"`
|
||||
Inet4Address []string `inbound:"inet4_address,omitempty"`
|
||||
Inet6Address []string `inbound:"inet6_address,omitempty"`
|
||||
StrictRoute bool `inbound:"strict_route,omitempty"`
|
||||
Inet4RouteAddress []string `inbound:"inet4_route_address,omitempty"`
|
||||
Inet6RouteAddress []string `inbound:"inet6_route_address,omitempty"`
|
||||
IncludeUID []uint32 `inbound:"include_uid,omitempty"`
|
||||
IncludeUIDRange []string `inbound:"include_uid_range,omitempty"`
|
||||
ExcludeUID []uint32 `inbound:"exclude_uid,omitempty"`
|
||||
ExcludeUIDRange []string `inbound:"exclude_uid_range,omitempty"`
|
||||
IncludeAndroidUser []int `inbound:"include_android_user,omitempty"`
|
||||
IncludePackage []string `inbound:"include_package,omitempty"`
|
||||
ExcludePackage []string `inbound:"exclude_package,omitempty"`
|
||||
EndpointIndependentNat bool `inbound:"endpoint_independent_nat,omitempty"`
|
||||
UDPTimeout int64 `inbound:"udp_timeout,omitempty"`
|
||||
}
|
||||
|
||||
func (o TunOption) Equal(config C.InboundConfig) bool {
|
||||
return optionToString(o) == optionToString(config)
|
||||
}
|
||||
|
||||
type Tun struct {
|
||||
*Base
|
||||
config *TunOption
|
||||
l *sing_tun.Listener
|
||||
tun LC.Tun
|
||||
}
|
||||
|
||||
func NewTun(options *TunOption) (*Tun, error) {
|
||||
base, err := NewBase(&options.BaseOption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stack, exist := C.StackTypeMapping[strings.ToLower(options.Stack)]
|
||||
if !exist {
|
||||
return nil, errors.New("invalid tun stack")
|
||||
}
|
||||
dnsHijack := make([]netip.AddrPort, 0, len(options.DNSHijack))
|
||||
for _, str := range options.DNSHijack {
|
||||
var a netip.AddrPort
|
||||
err = a.UnmarshalText([]byte(str))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dnsHijack = append(dnsHijack, a)
|
||||
}
|
||||
inet4Address, err := LC.StringSliceToListenPrefixSlice(options.Inet4Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inet6Address, err := LC.StringSliceToListenPrefixSlice(options.Inet6Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inet4RouteAddress, err := LC.StringSliceToListenPrefixSlice(options.Inet4RouteAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inet6RouteAddress, err := LC.StringSliceToListenPrefixSlice(options.Inet6RouteAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Tun{
|
||||
Base: base,
|
||||
config: options,
|
||||
tun: LC.Tun{
|
||||
Enable: true,
|
||||
Device: options.Device,
|
||||
Stack: stack,
|
||||
DNSHijack: dnsHijack,
|
||||
AutoRoute: options.AutoRoute,
|
||||
AutoDetectInterface: options.AutoDetectInterface,
|
||||
MTU: options.MTU,
|
||||
Inet4Address: inet4Address,
|
||||
Inet6Address: inet6Address,
|
||||
StrictRoute: options.StrictRoute,
|
||||
Inet4RouteAddress: inet4RouteAddress,
|
||||
Inet6RouteAddress: inet6RouteAddress,
|
||||
IncludeUID: options.IncludeUID,
|
||||
IncludeUIDRange: options.IncludeUIDRange,
|
||||
ExcludeUID: options.ExcludeUID,
|
||||
ExcludeUIDRange: options.ExcludeUIDRange,
|
||||
IncludeAndroidUser: options.IncludeAndroidUser,
|
||||
IncludePackage: options.IncludePackage,
|
||||
ExcludePackage: options.ExcludePackage,
|
||||
EndpointIndependentNat: options.EndpointIndependentNat,
|
||||
UDPTimeout: options.UDPTimeout,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Config implements constant.InboundListener
|
||||
func (t *Tun) Config() C.InboundConfig {
|
||||
return t.config
|
||||
}
|
||||
|
||||
// Address implements constant.InboundListener
|
||||
func (t *Tun) Address() string {
|
||||
return t.l.Address()
|
||||
}
|
||||
|
||||
// Listen implements constant.InboundListener
|
||||
func (t *Tun) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||
var err error
|
||||
t.l, err = sing_tun.New(t.tun, tcpIn, udpIn, t.Additions()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infoln("Tun[%s] proxy listening at: %s", t.Name(), t.Address())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close implements constant.InboundListener
|
||||
func (t *Tun) Close() error {
|
||||
return t.l.Close()
|
||||
}
|
||||
|
||||
var _ C.InboundListener = (*Tun)(nil)
|
|
@ -55,7 +55,7 @@ func (t *Tunnel) Close() error {
|
|||
if err == nil {
|
||||
err = udpErr
|
||||
} else {
|
||||
return fmt.Errorf("close tcp err: %t, close udp err: %t", err.Error(), udpErr.Error())
|
||||
return fmt.Errorf("close tcp err: %s, close udp err: %s", err.Error(), udpErr.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,8 @@ func (t *Tunnel) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter
|
|||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknow network type: %s", network)
|
||||
log.Warnln("unknown network type: %s, passed", network)
|
||||
continue
|
||||
}
|
||||
log.Infoln("Tunnel[%s](%s/%s)proxy listening at: %s", t.Name(), network, t.config.Target, t.Address())
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ type Vmess struct {
|
|||
*Base
|
||||
config *VmessOption
|
||||
l C.MultiAddrListener
|
||||
vs LC.VmessServer
|
||||
}
|
||||
|
||||
func NewVmess(options *VmessOption) (*Vmess, error) {
|
||||
|
@ -33,11 +34,23 @@ func NewVmess(options *VmessOption) (*Vmess, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
users := make([]LC.VmessUser, len(options.Users))
|
||||
for i, v := range options.Users {
|
||||
users[i] = LC.VmessUser{
|
||||
Username: v.Username,
|
||||
UUID: v.UUID,
|
||||
AlterID: v.AlterID,
|
||||
}
|
||||
}
|
||||
return &Vmess{
|
||||
Base: base,
|
||||
config: options,
|
||||
vs: LC.VmessServer{
|
||||
Enable: true,
|
||||
Listen: base.RawAddress(),
|
||||
Users: users,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
// Config implements constant.InboundListener
|
||||
|
@ -66,16 +79,7 @@ func (v *Vmess) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter)
|
|||
AlterID: v.AlterID,
|
||||
}
|
||||
}
|
||||
v.l, err = sing_vmess.New(
|
||||
LC.VmessServer{
|
||||
Enable: true,
|
||||
Listen: v.RawAddress(),
|
||||
Users: users,
|
||||
},
|
||||
tcpIn,
|
||||
udpIn,
|
||||
v.Additions()...,
|
||||
)
|
||||
v.l, err = sing_vmess.New(v.vs, tcpIn, udpIn, v.Additions()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -533,6 +533,7 @@ func ReCreateTun(tunConf LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.Pack
|
|||
}
|
||||
|
||||
tunLister, err = sing_tun.New(tunConf, tcpIn, udpIn)
|
||||
log.Infoln("[TUN] Tun adapter listening at: %s", tunLister.Address())
|
||||
}
|
||||
|
||||
func ReCreateRedirToTun(ifaceNames []string) {
|
||||
|
|
|
@ -62,6 +62,16 @@ func ParseListener(mapping map[string]any) (C.InboundListener, error) {
|
|||
return nil, err
|
||||
}
|
||||
listener, err = IN.NewTunnel(tunnelOption)
|
||||
case "tun":
|
||||
tunOption := &IN.TunOption{
|
||||
Stack: C.TunGvisor.String(),
|
||||
DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query
|
||||
}
|
||||
err = decoder.Decode(mapping, tunOption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listener, err = IN.NewTun(tunOption)
|
||||
case "shadowsocks":
|
||||
shadowsocksOption := &IN.ShadowSocksOption{}
|
||||
err = decoder.Decode(mapping, shadowsocksOption)
|
||||
|
|
|
@ -2,12 +2,14 @@ package sing_tun
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -29,6 +31,7 @@ type Listener struct {
|
|||
options LC.Tun
|
||||
handler *ListenerHandler
|
||||
tunName string
|
||||
addrStr string
|
||||
|
||||
tunIf tun.Tun
|
||||
tunStack tun.Stack
|
||||
|
@ -64,7 +67,13 @@ func CalculateInterfaceName(name string) (tunName string) {
|
|||
return
|
||||
}
|
||||
|
||||
func New(options LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (l *Listener, err error) {
|
||||
func New(options LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (l *Listener, err error) {
|
||||
if len(additions) == 0 {
|
||||
additions = []inbound.Addition{
|
||||
inbound.WithInName("DEFAULT-TUN"),
|
||||
inbound.WithSpecialRules(""),
|
||||
}
|
||||
}
|
||||
tunName := options.Device
|
||||
if tunName == "" {
|
||||
tunName = CalculateInterfaceName(InterfaceName)
|
||||
|
@ -116,6 +125,7 @@ func New(options LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapte
|
|||
TcpIn: tcpIn,
|
||||
UdpIn: udpIn,
|
||||
Type: C.TUN,
|
||||
Additions: additions,
|
||||
},
|
||||
DnsAdds: dnsAdds,
|
||||
}
|
||||
|
@ -211,7 +221,7 @@ func New(options LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapte
|
|||
|
||||
//l.openAndroidHotspot(tunOptions)
|
||||
|
||||
log.Infoln("[TUN] Tun adapter listening at: %s(%s,%s), mtu: %d, auto route: %v, ip stack: %s",
|
||||
l.addrStr = fmt.Sprintf("%s(%s,%s), mtu: %d, auto route: %v, ip stack: %s",
|
||||
tunName, tunOptions.Inet4Address, tunOptions.Inet6Address, tunMTU, options.AutoRoute, options.Stack)
|
||||
return
|
||||
}
|
||||
|
@ -286,3 +296,7 @@ func (l *Listener) Close() error {
|
|||
func (l *Listener) Config() LC.Tun {
|
||||
return l.options
|
||||
}
|
||||
|
||||
func (l *Listener) Address() string {
|
||||
return l.addrStr
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user