github.com/xraypb/Xray-core@v1.8.1/proxy/shadowsocks_2022/inbound_relay.go (about) 1 package shadowsocks_2022 2 3 import ( 4 "context" 5 "strconv" 6 "strings" 7 8 "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 9 C "github.com/sagernet/sing/common" 10 A "github.com/sagernet/sing/common/auth" 11 B "github.com/sagernet/sing/common/buf" 12 "github.com/sagernet/sing/common/bufio" 13 E "github.com/sagernet/sing/common/exceptions" 14 M "github.com/sagernet/sing/common/metadata" 15 N "github.com/sagernet/sing/common/network" 16 "github.com/xraypb/Xray-core/common" 17 "github.com/xraypb/Xray-core/common/buf" 18 "github.com/xraypb/Xray-core/common/log" 19 "github.com/xraypb/Xray-core/common/net" 20 "github.com/xraypb/Xray-core/common/protocol" 21 "github.com/xraypb/Xray-core/common/session" 22 "github.com/xraypb/Xray-core/common/uuid" 23 "github.com/xraypb/Xray-core/features/routing" 24 "github.com/xraypb/Xray-core/transport/internet/stat" 25 ) 26 27 func init() { 28 common.Must(common.RegisterConfig((*RelayServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 29 return NewRelayServer(ctx, config.(*RelayServerConfig)) 30 })) 31 } 32 33 type RelayInbound struct { 34 networks []net.Network 35 destinations []*RelayDestination 36 service *shadowaead_2022.RelayService[int] 37 } 38 39 func NewRelayServer(ctx context.Context, config *RelayServerConfig) (*RelayInbound, error) { 40 networks := config.Network 41 if len(networks) == 0 { 42 networks = []net.Network{ 43 net.Network_TCP, 44 net.Network_UDP, 45 } 46 } 47 inbound := &RelayInbound{ 48 networks: networks, 49 destinations: config.Destinations, 50 } 51 if !C.Contains(shadowaead_2022.List, config.Method) || !strings.Contains(config.Method, "aes") { 52 return nil, newError("unsupported method ", config.Method) 53 } 54 service, err := shadowaead_2022.NewRelayServiceWithPassword[int](config.Method, config.Key, 500, inbound) 55 if err != nil { 56 return nil, newError("create service").Base(err) 57 } 58 59 for i, destination := range config.Destinations { 60 if destination.Email == "" { 61 u := uuid.New() 62 destination.Email = "unnamed-destination-" + strconv.Itoa(i) + "-" + u.String() 63 } 64 } 65 err = service.UpdateUsersWithPasswords( 66 C.MapIndexed(config.Destinations, func(index int, it *RelayDestination) int { return index }), 67 C.Map(config.Destinations, func(it *RelayDestination) string { return it.Key }), 68 C.Map(config.Destinations, func(it *RelayDestination) M.Socksaddr { 69 return toSocksaddr(net.Destination{ 70 Address: it.Address.AsAddress(), 71 Port: net.Port(it.Port), 72 }) 73 }), 74 ) 75 if err != nil { 76 return nil, newError("create service").Base(err) 77 } 78 inbound.service = service 79 return inbound, nil 80 } 81 82 func (i *RelayInbound) Network() []net.Network { 83 return i.networks 84 } 85 86 func (i *RelayInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error { 87 inbound := session.InboundFromContext(ctx) 88 inbound.Name = "shadowsocks-2022-relay" 89 90 var metadata M.Metadata 91 if inbound.Source.IsValid() { 92 metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr()) 93 } 94 95 ctx = session.ContextWithDispatcher(ctx, dispatcher) 96 97 if network == net.Network_TCP { 98 return returnError(i.service.NewConnection(ctx, connection, metadata)) 99 } else { 100 reader := buf.NewReader(connection) 101 pc := &natPacketConn{connection} 102 for { 103 mb, err := reader.ReadMultiBuffer() 104 if err != nil { 105 buf.ReleaseMulti(mb) 106 return returnError(err) 107 } 108 for _, buffer := range mb { 109 packet := B.As(buffer.Bytes()).ToOwned() 110 err = i.service.NewPacket(ctx, pc, packet, metadata) 111 if err != nil { 112 packet.Release() 113 buf.ReleaseMulti(mb) 114 return err 115 } 116 buffer.Release() 117 } 118 } 119 } 120 } 121 122 func (i *RelayInbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 123 inbound := session.InboundFromContext(ctx) 124 userInt, _ := A.UserFromContext[int](ctx) 125 user := i.destinations[userInt] 126 inbound.User = &protocol.MemoryUser{ 127 Email: user.Email, 128 Level: uint32(user.Level), 129 } 130 ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ 131 From: metadata.Source, 132 To: metadata.Destination, 133 Status: log.AccessAccepted, 134 Email: user.Email, 135 }) 136 newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx)) 137 dispatcher := session.DispatcherFromContext(ctx) 138 link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP)) 139 if err != nil { 140 return err 141 } 142 outConn := &pipeConnWrapper{ 143 &buf.BufferedReader{Reader: link.Reader}, 144 link.Writer, 145 conn, 146 } 147 return bufio.CopyConn(ctx, conn, outConn) 148 } 149 150 func (i *RelayInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { 151 inbound := session.InboundFromContext(ctx) 152 userInt, _ := A.UserFromContext[int](ctx) 153 user := i.destinations[userInt] 154 inbound.User = &protocol.MemoryUser{ 155 Email: user.Email, 156 Level: uint32(user.Level), 157 } 158 ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ 159 From: metadata.Source, 160 To: metadata.Destination, 161 Status: log.AccessAccepted, 162 Email: user.Email, 163 }) 164 newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx)) 165 dispatcher := session.DispatcherFromContext(ctx) 166 destination := toDestination(metadata.Destination, net.Network_UDP) 167 link, err := dispatcher.Dispatch(ctx, destination) 168 if err != nil { 169 return err 170 } 171 outConn := &packetConnWrapper{ 172 Reader: link.Reader, 173 Writer: link.Writer, 174 Dest: destination, 175 } 176 return bufio.CopyPacketConn(ctx, conn, outConn) 177 } 178 179 func (i *RelayInbound) NewError(ctx context.Context, err error) { 180 if E.IsClosed(err) { 181 return 182 } 183 newError(err).AtWarning().WriteToLog() 184 }