chore: listeners support tunnel
This commit is contained in:
parent
8c58d8a8ad
commit
5c410b8df4
5 changed files with 118 additions and 8 deletions
|
@ -671,11 +671,13 @@ listeners:
|
|||
#listen: 0.0.0.0 # 默认监听 0.0.0.0
|
||||
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
|
||||
# udp: false # 默认 true
|
||||
|
||||
- name: http-in-1
|
||||
type: http
|
||||
port: 10809
|
||||
listen: 0.0.0.0
|
||||
# rule: sub-rule
|
||||
|
||||
- name: mixed-in-1
|
||||
type: mixed # HTTP(S) 和 SOCKS 代理混合
|
||||
port: 10810
|
||||
|
@ -729,3 +731,12 @@ listeners:
|
|||
# alpn:
|
||||
# - h3
|
||||
# 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
|
||||
}
|
||||
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":
|
||||
shadowsocksOption := &IN.ShadowSocksOption{}
|
||||
err = decoder.Decode(mapping, shadowsocksOption)
|
||||
|
|
|
@ -33,14 +33,14 @@ func (l *Listener) Close() error {
|
|||
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)
|
||||
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL)
|
||||
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)
|
||||
ctx.Metadata().SpecialProxy = l.proxy
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -67,7 +67,7 @@ func New(addr, target, proxy string, in chan<- C.ConnContext) (*Listener, error)
|
|||
}
|
||||
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()
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,21 +62,21 @@ func NewUDP(addr, target, proxy string, in chan<- C.PacketAdapter) (*PacketConn,
|
|||
}
|
||||
continue
|
||||
}
|
||||
sl.handleUDP(l, in, buf[:n], remoteAddr)
|
||||
sl.handleUDP(l, in, buf[:n], remoteAddr, additions...)
|
||||
}
|
||||
}()
|
||||
|
||||
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{
|
||||
pc: pc,
|
||||
rAddr: addr,
|
||||
payload: buf,
|
||||
}
|
||||
|
||||
ctx := inbound.NewPacket(l.target, packet, C.TUNNEL)
|
||||
ctx := inbound.NewPacket(l.target, packet, C.TUNNEL, additions...)
|
||||
ctx.Metadata().SpecialProxy = l.proxy
|
||||
select {
|
||||
case in <- ctx:
|
||||
|
|
Loading…
Reference in a new issue