mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
Merge VLESS to library
This commit is contained in:
parent
c18c545798
commit
d0b467671a
4
go.mod
4
go.mod
|
@ -27,7 +27,7 @@ require (
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220915084601-812e0864b45b
|
github.com/sagernet/sing-dns v0.0.0-20220915084601-812e0864b45b
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617
|
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220917033734-9b634758039d
|
github.com/sagernet/sing-vmess v0.0.0-20220921140858-b6a1bdee672f
|
||||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
|
||||||
github.com/spf13/cobra v1.5.0
|
github.com/spf13/cobra v1.5.0
|
||||||
|
@ -35,7 +35,7 @@ require (
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d
|
go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
||||||
golang.org/x/sys v0.0.0-20220913120320-3275c407cedc
|
golang.org/x/sys v0.0.0-20220913120320-3275c407cedc
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b
|
golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -153,8 +153,8 @@ github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDe
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617 h1:fNTNmylhB/UjoBLusmrFu2B1fat4OCkDkQXTgrE7ZsE=
|
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617 h1:fNTNmylhB/UjoBLusmrFu2B1fat4OCkDkQXTgrE7ZsE=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
github.com/sagernet/sing-tun v0.0.0-20220916073459-0032242c9617/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220917033734-9b634758039d h1:/GNWxSrQj4chFYk2jahIXNPdvUa9DW8IdgyqYFbq9oQ=
|
github.com/sagernet/sing-vmess v0.0.0-20220921140858-b6a1bdee672f h1:xyJ3Wbibcug4DxLi/FCHX2Td667SfieyZv645b8+eEE=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220917033734-9b634758039d/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
|
github.com/sagernet/sing-vmess v0.0.0-20220921140858-b6a1bdee672f/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM=
|
||||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
||||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
||||||
|
@ -196,8 +196,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 h1:a5Yg6ylndHHYJqIPrdq0AhvR6KTvDTAvgBtaidhEevY=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/v2ray"
|
"github.com/sagernet/sing-box/transport/v2ray"
|
||||||
"github.com/sagernet/sing-box/transport/vless"
|
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-vmess/packetaddr"
|
"github.com/sagernet/sing-vmess/packetaddr"
|
||||||
|
"github.com/sagernet/sing-vmess/vless"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
@ -105,7 +105,7 @@ func (h *VLESS) DialContext(ctx context.Context, network string, destination M.S
|
||||||
return h.client.DialEarlyConn(conn, destination), nil
|
return h.client.DialEarlyConn(conn, destination), nil
|
||||||
case N.NetworkUDP:
|
case N.NetworkUDP:
|
||||||
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
return h.client.DialPacketConn(conn, destination), nil
|
return h.client.DialEarlyPacketConn(conn, destination), nil
|
||||||
default:
|
default:
|
||||||
return nil, E.Extend(N.ErrUnknownNetwork, network)
|
return nil, E.Extend(N.ErrUnknownNetwork, network)
|
||||||
}
|
}
|
||||||
|
@ -130,11 +130,11 @@ func (h *VLESS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if h.xudp {
|
if h.xudp {
|
||||||
return h.client.DialXUDPPacketConn(conn, destination), nil
|
return h.client.DialEarlyXUDPPacketConn(conn, destination), nil
|
||||||
} else if h.packetAddr {
|
} else if h.packetAddr {
|
||||||
return dialer.NewResolvePacketConn(ctx, h.router, dns.DomainStrategyAsIS, packetaddr.NewConn(h.client.DialPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress}), destination)), nil
|
return dialer.NewResolvePacketConn(ctx, h.router, dns.DomainStrategyAsIS, packetaddr.NewConn(h.client.DialEarlyPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress}), destination)), nil
|
||||||
} else {
|
} else {
|
||||||
return h.client.DialPacketConn(conn, destination), nil
|
return h.client.DialEarlyPacketConn(conn, destination), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
package vless
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-vmess"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
key []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(userId string) (*Client, error) {
|
|
||||||
user := uuid.FromStringOrNil(userId)
|
|
||||||
if user == uuid.Nil {
|
|
||||||
user = uuid.NewV5(user, userId)
|
|
||||||
}
|
|
||||||
return &Client{key: user.Bytes()}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DialEarlyConn(conn net.Conn, destination M.Socksaddr) *Conn {
|
|
||||||
return &Conn{Conn: conn, key: c.key, command: vmess.CommandTCP, destination: destination}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DialPacketConn(conn net.Conn, destination M.Socksaddr) *PacketConn {
|
|
||||||
return &PacketConn{Conn: conn, key: c.key, destination: destination}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DialXUDPPacketConn(conn net.Conn, destination M.Socksaddr) vmess.PacketConn {
|
|
||||||
return vmess.NewXUDPConn(&Conn{Conn: conn, key: c.key, command: vmess.CommandMux, destination: destination}, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Conn struct {
|
|
||||||
net.Conn
|
|
||||||
key []byte
|
|
||||||
command byte
|
|
||||||
destination M.Socksaddr
|
|
||||||
requestWritten bool
|
|
||||||
responseRead bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
|
||||||
if !c.responseRead {
|
|
||||||
err = ReadResponse(c.Conn)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.responseRead = true
|
|
||||||
}
|
|
||||||
return c.Conn.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
|
||||||
if !c.requestWritten {
|
|
||||||
err = WriteRequest(c.Conn, Request{c.key, c.command, c.destination}, b)
|
|
||||||
if err == nil {
|
|
||||||
n = len(b)
|
|
||||||
}
|
|
||||||
c.requestWritten = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.Conn.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Upstream() any {
|
|
||||||
return c.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type PacketConn struct {
|
|
||||||
net.Conn
|
|
||||||
key []byte
|
|
||||||
destination M.Socksaddr
|
|
||||||
requestWritten bool
|
|
||||||
responseRead bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) Read(b []byte) (n int, err error) {
|
|
||||||
if !c.responseRead {
|
|
||||||
err = ReadResponse(c.Conn)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.responseRead = true
|
|
||||||
}
|
|
||||||
var length uint16
|
|
||||||
err = binary.Read(c.Conn, binary.BigEndian, &length)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cap(b) < int(length) {
|
|
||||||
return 0, io.ErrShortBuffer
|
|
||||||
}
|
|
||||||
return io.ReadFull(c.Conn, b[:length])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) Write(b []byte) (n int, err error) {
|
|
||||||
if !c.requestWritten {
|
|
||||||
err = WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination}, b)
|
|
||||||
if err == nil {
|
|
||||||
n = len(b)
|
|
||||||
}
|
|
||||||
c.requestWritten = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = binary.Write(c.Conn, binary.BigEndian, uint16(len(b)))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.Conn.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
||||||
defer buffer.Release()
|
|
||||||
dataLen := buffer.Len()
|
|
||||||
binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(dataLen))
|
|
||||||
if !c.requestWritten {
|
|
||||||
err := WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination}, buffer.Bytes())
|
|
||||||
c.requestWritten = true
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return common.Error(c.Conn.Write(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
||||||
n, err = c.Read(p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
||||||
return c.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) FrontHeadroom() int {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConn) Upstream() any {
|
|
||||||
return c.Conn
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
package vless
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-vmess"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
"github.com/sagernet/sing/common/rw"
|
|
||||||
)
|
|
||||||
|
|
||||||
const Version = 0
|
|
||||||
|
|
||||||
type Request struct {
|
|
||||||
UUID []byte
|
|
||||||
Command byte
|
|
||||||
Destination M.Socksaddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteRequest(writer io.Writer, request Request, payload []byte) error {
|
|
||||||
var requestLen int
|
|
||||||
requestLen += 1 // version
|
|
||||||
requestLen += 16 // uuid
|
|
||||||
requestLen += 1 // protobuf length
|
|
||||||
requestLen += 1 // command
|
|
||||||
if request.Command != vmess.CommandMux {
|
|
||||||
requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination)
|
|
||||||
}
|
|
||||||
requestLen += len(payload)
|
|
||||||
_buffer := buf.StackNewSize(requestLen)
|
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
common.Must(
|
|
||||||
buffer.WriteByte(Version),
|
|
||||||
common.Error(buffer.Write(request.UUID)),
|
|
||||||
buffer.WriteByte(0),
|
|
||||||
buffer.WriteByte(request.Command),
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.Command != vmess.CommandMux {
|
|
||||||
common.Must(vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination))
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Must1(buffer.Write(payload))
|
|
||||||
return common.Error(writer.Write(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func WritePacketRequest(writer io.Writer, request Request, payload []byte) error {
|
|
||||||
var requestLen int
|
|
||||||
requestLen += 1 // version
|
|
||||||
requestLen += 16 // uuid
|
|
||||||
requestLen += 1 // protobuf length
|
|
||||||
requestLen += 1 // command
|
|
||||||
requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination)
|
|
||||||
if len(payload) > 0 {
|
|
||||||
requestLen += 2
|
|
||||||
requestLen += len(payload)
|
|
||||||
}
|
|
||||||
_buffer := buf.StackNewSize(requestLen)
|
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
common.Must(
|
|
||||||
buffer.WriteByte(Version),
|
|
||||||
common.Error(buffer.Write(request.UUID)),
|
|
||||||
buffer.WriteByte(0),
|
|
||||||
buffer.WriteByte(vmess.CommandUDP),
|
|
||||||
vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination),
|
|
||||||
binary.Write(buffer, binary.BigEndian, uint16(len(payload))),
|
|
||||||
common.Error(buffer.Write(payload)),
|
|
||||||
)
|
|
||||||
return common.Error(writer.Write(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadResponse(reader io.Reader) error {
|
|
||||||
version, err := rw.ReadByte(reader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if version != Version {
|
|
||||||
return E.New("unknown version: ", version)
|
|
||||||
}
|
|
||||||
protobufLength, err := rw.ReadByte(reader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if protobufLength > 0 {
|
|
||||||
err = rw.SkipN(reader, int(protobufLength))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue