Chore: merge branch 'with-tun' into plus-pro
This commit is contained in:
commit
4d9d8b28ec
@ -225,6 +225,7 @@ proxies:
|
|||||||
network: tcp
|
network: tcp
|
||||||
servername: example.com
|
servername: example.com
|
||||||
# flow: xtls-rprx-direct # xtls-rprx-origin # enable XTLS
|
# flow: xtls-rprx-direct # xtls-rprx-origin # enable XTLS
|
||||||
|
# udp: true
|
||||||
# skip-cert-verify: true
|
# skip-cert-verify: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package outbound
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -128,8 +129,9 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||||||
c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig)
|
c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
// default tcp network
|
||||||
// handle TLS And XTLS
|
// handle TLS And XTLS
|
||||||
c, err = v.streamTLSOrXTLSConn(c, true)
|
c, err = v.streamTLSOrXTLSConn(c, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -213,7 +215,7 @@ func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||||
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
// vless use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||||
if !metadata.Resolved() {
|
if !metadata.Resolved() {
|
||||||
ip, err := resolver.ResolveIP(metadata.Host)
|
ip, err := resolver.ResolveIP(metadata.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -269,7 +271,7 @@ func parseVlessAddr(metadata *C.Metadata) *vless.DstAddr {
|
|||||||
copy(addr[1:], []byte(metadata.Host))
|
copy(addr[1:], []byte(metadata.Host))
|
||||||
}
|
}
|
||||||
|
|
||||||
port, _ := strconv.Atoi(metadata.DstPort)
|
port, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
return &vless.DstAddr{
|
return &vless.DstAddr{
|
||||||
UDP: metadata.NetWork == C.UDP,
|
UDP: metadata.NetWork == C.UDP,
|
||||||
AddrType: addrType,
|
AddrType: addrType,
|
||||||
@ -281,14 +283,21 @@ func parseVlessAddr(metadata *C.Metadata) *vless.DstAddr {
|
|||||||
type vlessPacketConn struct {
|
type vlessPacketConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
rAddr net.Addr
|
rAddr net.Addr
|
||||||
|
cache [2]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uc *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
func (uc *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||||
|
binary.BigEndian.PutUint16(uc.cache[:], uint16(len(b)))
|
||||||
|
_, _ = uc.Conn.Write(uc.cache[:])
|
||||||
return uc.Conn.Write(b)
|
return uc.Conn.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uc *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
func (uc *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||||
n, err := uc.Conn.Read(b)
|
n, err := uc.Conn.Read(uc.cache[:])
|
||||||
|
if err != nil {
|
||||||
|
return n, uc.rAddr, err
|
||||||
|
}
|
||||||
|
n, err = uc.Conn.Read(b)
|
||||||
return n, uc.rAddr, err
|
return n, uc.rAddr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func parserPacket(conn net.Conn) (socks5.Addr, error) {
|
|||||||
// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
|
// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
|
||||||
func getorigdst(fd uintptr) (socks5.Addr, error) {
|
func getorigdst(fd uintptr) (socks5.Addr, error) {
|
||||||
raw := syscall.RawSockaddrInet4{}
|
raw := syscall.RawSockaddrInet4{}
|
||||||
siz := unsafe.Sizeof(raw)
|
siz := uint32(unsafe.Sizeof(raw))
|
||||||
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
|
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
|
||||||
"github.com/Dreamacro/clash/listener/tun/device"
|
"github.com/Dreamacro/clash/listener/tun/device"
|
||||||
"github.com/Dreamacro/clash/listener/tun/device/iobased"
|
"github.com/Dreamacro/clash/listener/tun/device/iobased"
|
||||||
|
|
||||||
@ -22,6 +21,8 @@ type TUN struct {
|
|||||||
mtu uint32
|
mtu uint32
|
||||||
name string
|
name string
|
||||||
offset int
|
offset int
|
||||||
|
|
||||||
|
cache []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(name string, mtu uint32) (_ device.Device, err error) {
|
func Open(name string, mtu uint32) (_ device.Device, err error) {
|
||||||
@ -70,6 +71,10 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
|
|||||||
}
|
}
|
||||||
t.mtu = uint32(tunMTU)
|
t.mtu = uint32(tunMTU)
|
||||||
|
|
||||||
|
if t.offset > 0 {
|
||||||
|
t.cache = make([]byte, 65535)
|
||||||
|
}
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,19 +83,9 @@ func (t *TUN) Read(packet []byte) (int, error) {
|
|||||||
return t.nt.Read(packet, t.offset)
|
return t.nt.Read(packet, t.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := pool.Get(t.offset + cap(packet))
|
n, err := t.nt.Read(t.cache, t.offset)
|
||||||
defer func() {
|
|
||||||
_ = pool.Put(buff)
|
|
||||||
}()
|
|
||||||
|
|
||||||
n, err := t.nt.Read(buff, t.offset)
|
copy(packet, t.cache[t.offset:t.offset+n])
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = buff[:t.offset]
|
|
||||||
|
|
||||||
copy(packet, buff[t.offset:t.offset+n])
|
|
||||||
|
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
@ -100,7 +95,8 @@ func (t *TUN) Write(packet []byte) (int, error) {
|
|||||||
return t.nt.Write(packet, t.offset)
|
return t.nt.Write(packet, t.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = append(make([]byte, t.offset), packet...)
|
_ = t.cache[:t.offset]
|
||||||
|
packet = append(t.cache[:t.offset], packet...)
|
||||||
|
|
||||||
return t.nt.Write(packet, t.offset)
|
return t.nt.Write(packet, t.offset)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func TestClash_VlessTLS(t *testing.T) {
|
|||||||
TLS: true,
|
TLS: true,
|
||||||
SkipCertVerify: true,
|
SkipCertVerify: true,
|
||||||
ServerName: "example.org",
|
ServerName: "example.org",
|
||||||
UDP: false,
|
UDP: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.FailNow(t, err.Error())
|
assert.FailNow(t, err.Error())
|
||||||
@ -71,16 +71,16 @@ func TestClash_VlessXTLS(t *testing.T) {
|
|||||||
defer cleanContainer(id)
|
defer cleanContainer(id)
|
||||||
|
|
||||||
proxy, err := outbound.NewVless(outbound.VlessOption{
|
proxy, err := outbound.NewVless(outbound.VlessOption{
|
||||||
Name: "vless",
|
Name: "vless",
|
||||||
Server: localIP.String(),
|
Server: localIP.String(),
|
||||||
Port: 10002,
|
Port: 10002,
|
||||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||||
TLS: true,
|
TLS: true,
|
||||||
Flow: "xtls-rprx-direct",
|
|
||||||
//FlowShow: true,
|
|
||||||
SkipCertVerify: true,
|
SkipCertVerify: true,
|
||||||
ServerName: "example.org",
|
ServerName: "example.org",
|
||||||
UDP: false,
|
UDP: true,
|
||||||
|
Flow: "xtls-rprx-direct",
|
||||||
|
FlowShow: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.FailNow(t, err.Error())
|
assert.FailNow(t, err.Error())
|
||||||
|
Reference in New Issue
Block a user