コード例 #1
0
        private async Task HandleConnectRequestAsync(Request request, Memory <byte> buffer, CancellationToken cancellationToken = default)
        {
            // Connect to remote endpoint.
            EndpointSocket = ClientSocket.CreateNewOfSameType();
            EndpointSocket.Bind(new IPEndPoint(EndpointInterface, 0 /* any */));

            var error = null as SocketError?;

            try
            {
                switch (request)
                {
                case IpRequest ipRequest:
                    EndpointSocket = await EndpointSocket.ConnectAsync(ipRequest.Address, ipRequest.Port);

                    break;

                case DomainNameRequest domainRequest:
                    EndpointSocket = await EndpointSocket.ConnectAsync(domainRequest.DomainName, domainRequest.Port);

                    break;

                default:
                    throw new Exception("Unknown request type.");
                }
            }
            catch (SocketException e)
            {
                error = e.SocketErrorCode;
            }

            var localEndpoint  = EndpointSocket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(0, 0);
            var remoteEndpoint = EndpointSocket?.RemoteEndPoint as IPEndPoint ?? new IPEndPoint(0, 0);

            // The bind address and port should be the server local values during a CONNECT.

            var localAddress = localEndpoint.Address;

            if (localAddress.IsIPv4MappedToIPv6)
            {
                localAddress = localAddress.MapToIPv4();
            }

            var(portHigh, portLow) = Helpers.GetBytesFromPort(localEndpoint.Port);

            // Select the reply code based on any errors.

            var replyField = Helpers.GetSocksReply(error);

            // Send reply to client.

            var replyLength = 0;

            buffer.Span[0] = 0x05;       // VERSION
            buffer.Span[1] = replyField; // REPLY.
            buffer.Span[2] = 0x00;       // RESERVED.

            if (localAddress.AddressFamily == AddressFamily.InterNetwork)
            {
                buffer.Span[3] = 0x01; // ADDRESS TYPE (IPv4).
                localAddress.TryWriteBytes(buffer.Span.Slice(4, 4), out int written);
                buffer.Span[8] = portHigh;
                buffer.Span[9] = portLow;

                replyLength = 10;
            }
            else if (localAddress.AddressFamily == AddressFamily.InterNetworkV6)
            {
                buffer.Span[3] = 0x04; // ADDRESS TYPE (IPv6).
                localAddress.TryWriteBytes(buffer.Span.Slice(4, 16), out int written);
                buffer.Span[20] = portHigh;
                buffer.Span[21] = portLow;

                replyLength = 22;
            }
            else
            {
                throw new Exception("Unknown server-local bind address type.");
            }

            // Send a response to client regardless of failure.

            await ClientSocket.SendAsync(buffer.Slice(0, replyLength), cancellationToken);

            var sock = new Socket(SocketType.Dgram, ProtocolType.Udp);
            var buf  = new byte[4096];

            // In a failure scenario, ensure the SOCKS process does not continue.

            if (error != null)
            {
                throw new SocksException($"The connection failed gracefully with `{error}`.");
            }
        }