Files
v2ray_simple/proxy/vless/client.go
e1732a364fed a9a746ba2f 多项对接口的修改,为ss做准备:
取消Client的LocalAddr,改为 LocalTCPAddr 和 LocalUDPAddr
删除direct中的对应条目。这样可更清晰地配置双本地地址

将设置sendthrough设置双地址的代码移动到 proxy.newClient函数

这样不仅direct可指定不同的tcp和udp的本地地址,任何client协议都可以了

为ClientCreator 接口 添加 UseUDPAsMsgConn 方法,direct和ss返回true

在ss的client的EstablishUDPChannel进行自行拨号

在ss的server建立后,自动循环监听udp,绕过vs的基本监听机制。因为vs架构的限制,一个代理只能有一个唯一的传输层协议。

ServerCreator 接口 添加 AfterCommonConfServer 方法
2022-12-03 23:51:51 +08:00

226 lines
4.1 KiB
Go

package vless
import (
"bytes"
"io"
"net"
"net/url"
"strconv"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
)
func init() {
proxy.RegisterClient(Name, ClientCreator{})
}
type ClientCreator struct{ proxy.CreatorCommonStruct }
func (ClientCreator) UseUDPAsMsgConn() bool {
return false
}
func (ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) {
uuidStr := dc.Uuid
id, err := utils.NewV2rayUser(uuidStr)
if err != nil {
return nil, err
}
c := Client{
user: id,
}
v := dc.Version
if v > 0 {
if v == 1 {
c.version = 1
c.use_mux = dc.Mux
if dc.Extra != nil {
if thing := dc.Extra["vless1_udp_multi"]; thing != nil {
if udp_multi, ok := thing.(bool); ok && udp_multi {
c.udp_multi = true
}
}
}
} else {
return nil, utils.ErrInErr{ErrDesc: "given version bigger than 1", ErrDetail: utils.ErrUnImplemented}
}
}
return &c, nil
}
func (ClientCreator) URLToDialConf(url *url.URL, dc *proxy.DialConf, format int) (*proxy.DialConf, error) {
switch format {
case proxy.UrlStandardFormat:
if dc == nil {
dc = &proxy.DialConf{}
uuidStr := url.User.Username()
dc.Uuid = uuidStr
}
return dc, nil
default:
return dc, utils.ErrUnImplemented
}
}
// 实现 proxy.UserClient
type Client struct {
proxy.Base
version int
user utils.V2rayUser
udp_multi bool
use_mux bool
}
func (*Client) GetCreator() proxy.ClientCreator {
return ClientCreator{}
}
func (c *Client) Name() string {
if c.version == 0 {
return Name
}
return Name + "_" + strconv.Itoa(c.version)
// 根据 https://forum.golangbridge.org/t/fmt-sprintf-vs-string-concatenation/23006
// 直接 + 比 fmt.Sprintf 快不少.
}
func (c *Client) Version() int { return c.version }
func (c *Client) GetUser() utils.User {
return c.user
}
// 我们只支持 vless v1 的 mux
func (c *Client) HasInnerMux() (int, string) {
if c.version == 1 && c.use_mux {
return 2, "simplesocks"
} else {
return 0, ""
}
}
func (c *Client) IsUDP_MultiChannel() bool {
return c.udp_multi
}
func (c *Client) Handshake(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (io.ReadWriteCloser, error) {
var err error
port := target.Port
addr, atyp := target.AddressBytes()
var buf *bytes.Buffer
if c.use_mux {
buf = c.getBufWithCmd(CmdMux)
} else {
buf = c.getBufWithCmd(CmdTCP)
}
buf.WriteByte(byte(uint16(port) >> 8))
buf.WriteByte(byte(uint16(port) << 8 >> 8))
buf.WriteByte(atyp)
buf.Write(addr)
if len(firstPayload) > 0 {
buf.Write(firstPayload)
utils.PutBytes(firstPayload)
}
_, err = underlay.Write(buf.Bytes())
utils.PutBuf(buf)
if err != nil {
return nil, err
}
if c.version == 0 {
uc := &UserTCPConn{
Conn: underlay,
V2rayUser: c.user,
version: c.version,
underlayIsBasic: netLayer.IsBasicConn(underlay),
}
if r, rr, mr := netLayer.IsConnGoodForReadv(underlay); r > 0 {
uc.rr = rr
uc.mr = mr
}
return uc, nil
} else {
return underlay, nil
}
}
func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (netLayer.MsgConn, error) {
buf := c.getBufWithCmd(CmdUDP)
port := target.Port
buf.WriteByte(byte(uint16(port) >> 8))
buf.WriteByte(byte(uint16(port) << 8 >> 8))
addr, atyp := target.AddressBytes()
buf.WriteByte(atyp)
buf.Write(addr)
target.Network = "udp"
uc := &UDPConn{
Conn: underlay,
V2rayUser: c.user,
version: c.version,
isClientEnd: true,
raddr: target,
udp_multi: c.udp_multi,
handshakeBuf: buf,
fullcone: c.IsFullcone,
}
if len(firstPayload) == 0 {
return uc, nil
} else {
return uc, uc.WriteMsgTo(firstPayload, target)
}
}
func (c *Client) getBufWithCmd(cmd byte) *bytes.Buffer {
v := c.version
buf := utils.GetBuf()
buf.WriteByte(byte(c.version)) //version
buf.Write(c.user[:])
if v == 0 {
buf.WriteByte(0) //addon length
} else {
switch {
default:
buf.WriteByte(0) //no addon
case c.udp_multi:
buf.WriteByte(addon_udp_multi_flag)
}
}
buf.WriteByte(cmd) // cmd
return buf
}