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