chore: listeners support tunnel
This commit is contained in:
parent
a6303be23b
commit
9b5e35c96c
5 changed files with 118 additions and 8 deletions
|
@ -671,11 +671,13 @@ listeners:
|
||||||
#listen: 0.0.0.0 # 默认监听 0.0.0.0
|
#listen: 0.0.0.0 # 默认监听 0.0.0.0
|
||||||
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
|
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
|
||||||
# udp: false # 默认 true
|
# udp: false # 默认 true
|
||||||
|
|
||||||
- name: http-in-1
|
- name: http-in-1
|
||||||
type: http
|
type: http
|
||||||
port: 10809
|
port: 10809
|
||||||
listen: 0.0.0.0
|
listen: 0.0.0.0
|
||||||
# rule: sub-rule
|
# rule: sub-rule
|
||||||
|
|
||||||
- name: mixed-in-1
|
- name: mixed-in-1
|
||||||
type: mixed # HTTP(S) 和 SOCKS 代理混合
|
type: mixed # HTTP(S) 和 SOCKS 代理混合
|
||||||
port: 10810
|
port: 10810
|
||||||
|
@ -729,3 +731,12 @@ listeners:
|
||||||
# alpn:
|
# alpn:
|
||||||
# - h3
|
# - h3
|
||||||
# max-udp-relay-packet-size: 1500
|
# max-udp-relay-packet-size: 1500
|
||||||
|
|
||||||
|
- name: tunnel-in-1
|
||||||
|
type: tunnel
|
||||||
|
port: 10816
|
||||||
|
listen: 0.0.0.0
|
||||||
|
# rule: sub-rule
|
||||||
|
network: [ tcp, udp ]
|
||||||
|
target: target.com
|
||||||
|
|
||||||
|
|
92
listener/inbound/tunnel.go
Normal file
92
listener/inbound/tunnel.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
package inbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"github.com/Dreamacro/clash/listener/tunnel"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TunnelOption struct {
|
||||||
|
BaseOption
|
||||||
|
Network []string `inbound:"network"`
|
||||||
|
Target string `inbound:"target"`
|
||||||
|
Proxy string `inbound:"proxy,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o TunnelOption) Equal(config C.InboundConfig) bool {
|
||||||
|
return optionToString(o) == optionToString(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tunnel struct {
|
||||||
|
*Base
|
||||||
|
config *TunnelOption
|
||||||
|
ttl *tunnel.Listener
|
||||||
|
tul *tunnel.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTunnel(options *TunnelOption) (*Tunnel, error) {
|
||||||
|
base, err := NewBase(&options.BaseOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Tunnel{
|
||||||
|
Base: base,
|
||||||
|
config: options,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config implements constant.InboundListener
|
||||||
|
func (t *Tunnel) Config() C.InboundConfig {
|
||||||
|
return t.config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements constant.InboundListener
|
||||||
|
func (t *Tunnel) Close() error {
|
||||||
|
var err error
|
||||||
|
if t.ttl != nil {
|
||||||
|
if tcpErr := t.ttl.Close(); tcpErr != nil {
|
||||||
|
err = tcpErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if t.tul != nil {
|
||||||
|
if udpErr := t.tul.Close(); udpErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
err = udpErr
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("close tcp err: %t, close udp err: %t", err.Error(), udpErr.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address implements constant.InboundListener
|
||||||
|
func (t *Tunnel) Address() string {
|
||||||
|
return t.ttl.Address()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen implements constant.InboundListener
|
||||||
|
func (t *Tunnel) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error {
|
||||||
|
var err error
|
||||||
|
for _, network := range t.config.Network {
|
||||||
|
switch network {
|
||||||
|
case "tcp":
|
||||||
|
if t.ttl, err = tunnel.New(t.RawAddress(), t.config.Target, t.config.Proxy, tcpIn, t.Additions()...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "udp":
|
||||||
|
if t.tul, err = tunnel.NewUDP(t.RawAddress(), t.config.Target, t.config.Proxy, udpIn, t.Additions()...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknow network type: %s", network)
|
||||||
|
}
|
||||||
|
log.Infoln("Tunnel[%s](%s/%s)proxy listening at: %s", t.Name(), network, t.config.Target, t.Address())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ C.InboundListener = (*Tunnel)(nil)
|
|
@ -55,6 +55,13 @@ func ParseListener(mapping map[string]any) (C.InboundListener, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
listener, err = IN.NewMixed(mixedOption)
|
listener, err = IN.NewMixed(mixedOption)
|
||||||
|
case "tunnel":
|
||||||
|
tunnelOption := &IN.TunnelOption{}
|
||||||
|
err = decoder.Decode(mapping, tunnelOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener, err = IN.NewTunnel(tunnelOption)
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
shadowsocksOption := &IN.ShadowSocksOption{}
|
shadowsocksOption := &IN.ShadowSocksOption{}
|
||||||
err = decoder.Decode(mapping, shadowsocksOption)
|
err = decoder.Decode(mapping, shadowsocksOption)
|
||||||
|
|
|
@ -33,14 +33,14 @@ func (l *Listener) Close() error {
|
||||||
return l.listener.Close()
|
return l.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) handleTCP(conn net.Conn, in chan<- C.ConnContext) {
|
func (l *Listener) handleTCP(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||||
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL)
|
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)
|
||||||
ctx.Metadata().SpecialProxy = l.proxy
|
ctx.Metadata().SpecialProxy = l.proxy
|
||||||
in <- ctx
|
in <- ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(addr, target, proxy string, in chan<- C.ConnContext) (*Listener, error) {
|
func New(addr, target, proxy string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) {
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -67,7 +67,7 @@ func New(addr, target, proxy string, in chan<- C.ConnContext) (*Listener, error)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go rl.handleTCP(c, in)
|
go rl.handleTCP(c, in, additions...)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ func (l *PacketConn) Close() error {
|
||||||
return l.conn.Close()
|
return l.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUDP(addr, target, proxy string, in chan<- C.PacketAdapter) (*PacketConn, error) {
|
func NewUDP(addr, target, proxy string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*PacketConn, error) {
|
||||||
l, err := net.ListenPacket("udp", addr)
|
l, err := net.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -62,21 +62,21 @@ func NewUDP(addr, target, proxy string, in chan<- C.PacketAdapter) (*PacketConn,
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sl.handleUDP(l, in, buf[:n], remoteAddr)
|
sl.handleUDP(l, in, buf[:n], remoteAddr, additions...)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return sl, nil
|
return sl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *PacketConn) handleUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr) {
|
func (l *PacketConn) handleUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr, additions ...inbound.Addition) {
|
||||||
packet := &packet{
|
packet := &packet{
|
||||||
pc: pc,
|
pc: pc,
|
||||||
rAddr: addr,
|
rAddr: addr,
|
||||||
payload: buf,
|
payload: buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := inbound.NewPacket(l.target, packet, C.TUNNEL)
|
ctx := inbound.NewPacket(l.target, packet, C.TUNNEL, additions...)
|
||||||
ctx.Metadata().SpecialProxy = l.proxy
|
ctx.Metadata().SpecialProxy = l.proxy
|
||||||
select {
|
select {
|
||||||
case in <- ctx:
|
case in <- ctx:
|
||||||
|
|
Loading…
Reference in a new issue