mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
取消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 方法
226 lines
4.1 KiB
Go
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
|
|
}
|