github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/mixed/mixed.go (about) 1 package mixed 2 3 import ( 4 "context" 5 "io" 6 "net" 7 8 "github.com/Asutorufa/yuhaiin/pkg/log" 9 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 10 "github.com/Asutorufa/yuhaiin/pkg/net/proxy/http" 11 "github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks4a" 12 "github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5" 13 "github.com/Asutorufa/yuhaiin/pkg/protos/config/listener" 14 "github.com/Asutorufa/yuhaiin/pkg/utils/pool" 15 ) 16 17 type Mixed struct { 18 lis net.Listener 19 20 s5c *netapi.ChannelListener 21 s5 netapi.Accepter 22 23 s4c *netapi.ChannelListener 24 s4 netapi.Accepter 25 26 httpc *netapi.ChannelListener 27 http netapi.Accepter 28 29 *netapi.ChannelServer 30 } 31 32 func init() { 33 listener.RegisterProtocol(NewServer) 34 } 35 36 func NewServer(o *listener.Inbound_Mix) func(lis netapi.Listener) (netapi.Accepter, error) { 37 return func(ii netapi.Listener) (netapi.Accepter, error) { 38 lis, err := ii.Stream(context.TODO()) 39 if err != nil { 40 return nil, err 41 } 42 43 mix := &Mixed{ 44 lis: lis, 45 ChannelServer: netapi.NewChannelServer(), 46 } 47 48 mix.s5c = netapi.NewChannelListener(lis.Addr()) 49 mix.s5, err = socks5.NewServer(&listener.Inbound_Socks5{ 50 Socks5: &listener.Socks5{ 51 Host: o.Mix.Host, 52 Username: o.Mix.Username, 53 Password: o.Mix.Password, 54 Udp: true, 55 }, 56 })(netapi.PatchStream(mix.s5c, ii)) 57 if err != nil { 58 mix.Close() 59 return nil, err 60 } 61 s5 := mix.s5.(*socks5.Server) 62 s5.ChannelServer.Close() 63 s5.ChannelServer = mix.ChannelServer 64 65 mix.s4c = netapi.NewChannelListener(lis.Addr()) 66 mix.s4, err = socks4a.NewServer(&listener.Inbound_Socks4A{ 67 Socks4A: &listener.Socks4A{ 68 Host: o.Mix.Host, 69 Username: o.Mix.Username, 70 }, 71 })(netapi.PatchStream(mix.s4c, ii)) 72 if err != nil { 73 mix.Close() 74 return nil, err 75 } 76 s4 := mix.s4.(*socks4a.Server) 77 s4.ChannelServer.Close() 78 s4.ChannelServer = mix.ChannelServer 79 80 mix.httpc = netapi.NewChannelListener(lis.Addr()) 81 mix.http, err = http.NewServer(&listener.Inbound_Http{ 82 Http: &listener.Http{ 83 Host: o.Mix.Host, 84 Username: o.Mix.Username, 85 Password: o.Mix.Password, 86 }, 87 })(netapi.PatchStream(mix.httpc, ii)) 88 if err != nil { 89 mix.Close() 90 return nil, err 91 } 92 http := mix.http.(*http.Server) 93 http.ChannelServer.Close() 94 http.ChannelServer = mix.ChannelServer 95 96 go func() { 97 defer mix.Close() 98 if err := mix.handle(); err != nil { 99 log.Debug("mixed handle failed", "err", err) 100 } 101 }() 102 103 return mix, nil 104 } 105 } 106 107 func (m *Mixed) Close() error { 108 m.ChannelServer.Close() 109 noneNilClose(m.s5c) 110 noneNilClose(m.s5) 111 noneNilClose(m.s4c) 112 noneNilClose(m.s4) 113 noneNilClose(m.httpc) 114 noneNilClose(m.http) 115 return m.lis.Close() 116 } 117 118 func noneNilClose(i io.Closer) { 119 if c, ok := i.(*netapi.ChannelListener); ok { 120 if c != nil { 121 _ = c.Close() 122 } 123 124 return 125 } 126 127 if i != nil { 128 _ = i.Close() 129 } 130 } 131 132 func (m *Mixed) handle() error { 133 for { 134 conn, err := m.lis.Accept() 135 if err != nil { 136 log.Error("mixed accept failed", "err", err) 137 138 if ne, ok := err.(net.Error); ok && ne.Temporary() { 139 continue 140 } 141 return err 142 } 143 144 go func() { 145 protocol := pool.GetBytesBuffer(pool.DefaultSize) 146 147 n, err := protocol.ReadFrom(conn) 148 if err != nil || n <= 0 { 149 conn.Close() 150 return 151 } 152 153 conn = netapi.NewPrefixBytesConn(conn, protocol) 154 155 switch protocol.Bytes()[0] { 156 case 0x05: 157 m.s5c.NewConn(conn) 158 case 0x04: 159 m.s4c.NewConn(conn) 160 default: 161 m.httpc.NewConn(conn) 162 } 163 }() 164 } 165 }