Files
v2ray_simple/proxy/trojan/client.go
T
e1732a364fed 40082026e8 修订代码,完善gui配置代理的功能;url打印出path;其他:
修复quic关闭时闪退的bug;
url打印时若未配置network,去掉首部的加号

Uuid -> UUID
2022-12-28 21:01:20 +08:00

167 lines
3.4 KiB
Go

package trojan
import (
"bytes"
"errors"
"io"
"net"
"net/url"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
)
func init() {
proxy.RegisterClient(Name, ClientCreator{})
}
//作为对照,可以参考 https://github.com/p4gefau1t/trojan-go/blob/master/tunnel/trojan/client.go
type ClientCreator struct{ proxy.CreatorCommonStruct }
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 nil, utils.ErrUnImplemented
}
}
func (ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) {
uuidStr := dc.UUID
c := Client{
use_mux: dc.Mux,
User: NewUserByPlainTextPassword(uuidStr),
}
return &c, nil
}
type Client struct {
proxy.Base
User
use_mux bool
}
func (*Client) GetCreator() proxy.ClientCreator {
return ClientCreator{}
}
func (*Client) Name() string {
return Name
}
func (c *Client) HasInnerMux() (int, string) {
if c.use_mux {
return 2, "simplesocks"
} else {
return 0, ""
}
}
func (c *Client) GetUser() utils.User {
return c.User
}
func WriteAddrToBuf(target netLayer.Addr, buf *bytes.Buffer) {
if len(target.IP) > 0 {
if ip4 := target.IP.To4(); ip4 == nil {
buf.WriteByte(ATypIP6)
buf.Write(target.IP)
} else {
buf.WriteByte(ATypIP4)
buf.Write(ip4)
}
} else if l := len(target.Name); l > 0 {
buf.WriteByte(ATypDomain)
buf.WriteByte(byte(l))
buf.WriteString(target.Name)
}
buf.WriteByte(byte(target.Port >> 8))
buf.WriteByte(byte(target.Port << 8 >> 8))
buf.Write(crlf)
}
func (c *Client) Handshake(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (io.ReadWriteCloser, error) {
if target.Port <= 0 {
return nil, errors.New("trojan Client Handshake failed, target port invalid")
}
buf := utils.GetBuf()
buf.WriteString(c.AuthStr())
buf.Write(crlf)
if c.use_mux {
buf.WriteByte(CmdMux)
} else {
buf.WriteByte(CmdConnect)
}
WriteAddrToBuf(target, buf)
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.use_mux {
// we return underlay directly, the caller can call HasInnerMux method to see whether we use innerMux or not.
return underlay, nil
} else {
// 发现直接返回 underlay 反倒无法利用readv, 所以还是统一用包装过的. 目前利用readv是可以加速的.
uc := &UserTCPConn{
Conn: underlay,
User: c.User,
underlayIsBasic: netLayer.IsBasicConn(underlay),
}
if mw, ok := underlay.(utils.MultiWriter); ok {
uc.mw = mw
}
return uc, nil
}
}
func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (netLayer.MsgConn, error) {
if target.Port <= 0 {
return nil, utils.ErrInErr{ErrDesc: "trojan Client EstablishUDPChannel failed, target port invalid", Data: target}
}
buf := utils.GetBuf()
buf.WriteString(c.AuthStr())
buf.Write(crlf)
buf.WriteByte(CmdUDPAssociate)
WriteAddrToBuf(target, buf)
uc := NewUDPConn(underlay, nil, c.IsFullcone)
uc.User = c.User
uc.handshakeBuf = buf
if len(firstPayload) == 0 {
return uc, nil
} else {
return uc, uc.WriteMsg(firstPayload, target)
}
}