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

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

247 lines
4.9 KiB
Go

package shadowsocks
import (
"bytes"
"io"
"log"
"net"
"net/url"
"sync"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
"github.com/shadowsocks/go-shadowsocks2/core"
"go.uber.org/zap"
)
func init() {
proxy.RegisterServer(Name, &ServerCreator{})
}
type ServerCreator struct{ proxy.CreatorCommonStruct }
func (ServerCreator) MultiTransportLayer() bool {
return true
}
func (ServerCreator) NewServer(lc *proxy.ListenConf) (proxy.Server, error) {
if lc.Network == "" {
lc.Network = netLayer.DualNetworkName
}
uuidStr := lc.UUID
var mp MethodPass
if mp.InitWithStr(uuidStr) {
return newServer(mp, lc), nil
}
return nil, utils.ErrNilOrWrongParameter
}
func (ServerCreator) URLToListenConf(u *url.URL, lc *proxy.ListenConf, format int) (*proxy.ListenConf, error) {
if format != proxy.UrlStandardFormat {
return lc, utils.ErrUnImplemented
}
if lc == nil {
lc = &proxy.ListenConf{}
}
if p, set := u.User.Password(); set {
lc.UUID = "method:" + u.User.Username() + "\npass:" + p
}
return lc, nil
}
func (ServerCreator) AfterCommonConfServer(ps proxy.Server) (err error) {
s := ps.(*Server)
if s.TransportLayer != "tcp" {
s.LUA, err = net.ResolveUDPAddr("udp", s.AddrStr())
}
return
}
// 目前的实现只支持单用户
type Server struct {
proxy.Base
*utils.MultiUserMap
cipher core.Cipher
m sync.RWMutex
udpMsgConnMap map[netLayer.HashableAddr]*serverMsgConn
mp MethodPass
}
func newServer(info MethodPass, lc *proxy.ListenConf) *Server {
s := &Server{
cipher: initShadowCipher(info),
udpMsgConnMap: make(map[netLayer.HashableAddr]*serverMsgConn),
mp: info,
}
return s
}
func (*Server) Name() string {
return Name
}
func (s *Server) Network() string {
if s.TransportLayer == "" {
return netLayer.DualNetworkName
} else {
return s.TransportLayer
}
}
func (s *Server) SelfListen() (is bool, _, udp int) {
switch n := s.Network(); n {
case "", netLayer.DualNetworkName:
udp = 1
case "tcp":
case "udp":
udp = 1
}
is = udp > 0
return
}
func (s *Server) Handshake(underlay net.Conn) (result net.Conn, _ netLayer.MsgConn, targetAddr netLayer.Addr, returnErr error) {
stream := s.cipher.StreamConn(underlay)
readbs := utils.GetBytes(utils.MTU)
wholeReadLen, err := stream.Read(readbs)
if err != nil {
returnErr = utils.ErrInErr{ErrDesc: "read underlay failed", ErrDetail: err, Data: wholeReadLen}
return
}
readbuf := bytes.NewBuffer(readbs[:wholeReadLen])
goto realPart
errorPart:
//所返回的 buffer 必须包含所有数据,而 bytes.Buffer 是不支持回退的,所以只能重新 New
returnErr = &utils.ErrBuffer{
Err: returnErr,
Buf: bytes.NewBuffer(readbs[:wholeReadLen]),
}
return
realPart:
targetAddr, err = GetAddrFrom(readbuf)
if err != nil {
returnErr = err
goto errorPart
}
result = &proxy.UserReadWrapper{
ReadWrapper: netLayer.ReadWrapper{
Conn: stream,
OptionalReader: io.MultiReader(readbuf, stream),
RemainFirstBufLen: readbuf.Len(),
},
User: s.mp,
}
return
}
func (m *Server) removeUDPByHash(hash netLayer.HashableAddr) {
m.Lock()
delete(m.udpMsgConnMap, hash)
m.Unlock()
}
// 非阻塞
func (s *Server) StartListen(_ func(netLayer.TCPRequestInfo), udpFunc func(netLayer.UDPRequestInfo)) io.Closer {
uc, err := net.ListenUDP("udp", s.LUA)
if err != nil {
log.Panicln("shadowsocks listen udp failed", err)
}
pc := s.cipher.PacketConn(uc)
if ce := utils.CanLogInfo("shadowsocks listening udp"); ce != nil {
ce.Write(zap.String("listen addr", s.LUA.String()))
}
//逻辑完全类似tproxy,使用一个map存储不同终端的链接
go func() {
for {
bs := utils.GetPacket()
n, addr, err := pc.ReadFrom(bs)
if err != nil {
return
}
ad, err := netLayer.NewAddrFromAny(addr)
if err != nil {
if ce := utils.CanLogWarn("shadowsocks GetAddrFrom err"); ce != nil {
ce.Write(zap.Error(err))
}
return
}
hash := ad.GetHashable()
s.m.RLock()
conn, found := s.udpMsgConnMap[hash]
s.m.RUnlock()
if !found {
conn = &serverMsgConn{
raddr: addr,
ourPacketConn: pc,
readChan: make(chan netLayer.AddrData, 5),
closeChan: make(chan struct{}),
server: s,
hash: hash,
User: s.mp,
}
conn.InitEasyDeadline()
s.m.Lock()
s.udpMsgConnMap[hash] = conn
s.m.Unlock()
}
readbuf := bytes.NewBuffer(bs[:n])
destAddr, err := GetAddrFrom(readbuf)
if err != nil {
if ce := utils.CanLogWarn("shadowsocks GetAddrFrom err"); ce != nil {
ce.Write(zap.Error(err))
}
continue
}
destAddr.Network = "udp"
conn.readChan <- netLayer.AddrData{Data: readbuf.Bytes(), Addr: destAddr}
if !found {
go udpFunc(netLayer.UDPRequestInfo{
MsgConn: conn, Target: destAddr,
})
}
}
}()
return uc
}