Пример #1
0
        public static Destination.Destination ParseDestinationFromRequest(ReadOnlySpan <byte> payload)
        {
            if (payload.Length < 8)
            {
                throw RequestTooShortException;
            }
            if (payload[0] != 5)
            {
                throw BadRequestException;
            }
            TransportProtocol protocol;

            switch (payload[1])
            {
            case 1:
                protocol = TransportProtocol.Tcp;
                break;

            case 3:
                protocol = TransportProtocol.Udp;
                break;

            default:
                throw UnknownTypeException;
            }
            if (Adapter.Destination.Destination.TryParseSocks5StyleAddress(payload.Slice(3), out Destination.Destination destination, protocol) == 0)
            {
                throw RequestTooShortException;
            }

            // Some SOCKS5 clients (e.g. curl) can resolve IP addresses locally.
            // In this case, we got a fake IP address and need to
            // convert it back to the corresponding domain name.
            switch (destination.Host)
            {
            case Ipv4Host ipv4:
                destination = new Destination.Destination(DnsProxyServer.TryLookup(ipv4.Data), destination.Port, protocol);
                break;
            }
            return(destination);
        }
Пример #2
0
        internal TunSocketAdapter(TcpSocket socket, TunInterface tun, IRemoteAdapter remoteAdapter)
        {
            Interlocked.Increment(ref OpenCount);
            var pipe = new Pipe();

            inboundReader = pipe.Reader;
            inboundWriter = pipe.Writer;
            _socket       = socket;
            _tun          = tun;

            socket.DataReceived += Socket_DataReceived;
            socket.DataSent     += Socket_DataSent;
            socket.SocketError  += Socket_SocketError;
            socket.RecvFinished += Socket_RecvFinished;

            // Resolve destination host
            var host = DnsProxyServer.TryLookup(socket.RemoteAddr);

            Destination = new Destination.Destination(host, socket.RemotePort, TransportProtocol.Tcp);

            this.remoteAdapter = remoteAdapter;
            StartPush();
            Init();
        }
Пример #3
0
        async public void Init()
        {
            try
            {
                await r.ConnectAsync(server, port);
            }
            catch (Exception)
            {
                Debug.WriteLine("Error connecting to remote");
                return;
            }
            Debug.WriteLine("Connected");

            /*
             * var header = new byte[7];
             * header[0] = 0x01;
             * header[1] = (byte)(_socket.RemoteAddr & 0xFF);
             * header[2] = (byte)(_socket.RemoteAddr >> 8 & 0xFF);
             * header[3] = (byte)(_socket.RemoteAddr >> 16 & 0xFF);
             * header[4] = (byte)(_socket.RemoteAddr >> 24);
             * header[5] = (byte)(_socket.RemotePort >> 8);
             * header[6] = (byte)(_socket.RemotePort & 0xFF);
             */
            string domain = DnsProxyServer.Lookup((byte)(_socket.RemoteAddr >> 24 & 0xFF));
            var    header = new byte[domain.Length + 4];

            header[0] = 0x03;
            header[1] = (byte)domain.Length;
            Encoding.ASCII.GetBytes(domain).CopyTo(header, 2);
            header[header.Length - 2] = (byte)(_socket.RemotePort >> 8);
            header[header.Length - 1] = (byte)(_socket.RemotePort & 0xFF);

            // Let header be sent first
            remoteConnected = true;
            SendToRemote(header);

            byte[] remotebuf = new byte[2048];
            while (r.Connected)
            {
                while (sendBuffers.Count > 1)
                {
                    checkSendBufferHandle.WaitOne();
                    checkSendBufferHandle.Reset();
                }
                try
                {
                    var len = await r.ReceiveAsync(new ArraySegment <byte>(remotebuf), SocketFlags.None);

                    if (len == 0)
                    {
                        Debug.WriteLine("Empty run");
                        break;
                    }
                    Debug.WriteLine($"Received {len} bytes");
                    RemoteReceived(remotebuf.Take(len).ToArray());
                }
                catch (Exception)
                {
                    break;
                }
            }

            DisconnectRemote();
        }
Пример #4
0
        public async void Init()
        {
            try
            {
                await r.ConnectAsync(server, port);

                networkStream = r.GetStream();
            }
            catch (Exception)
            {
                Debug.WriteLine("Error connecting to remote");
                DisconnectRemote();
                Reset();
                return;
            }
            Debug.WriteLine("Connected");

            /*
             * var header = new byte[7];
             * header[0] = 0x01;
             * header[1] = (byte)(_socket.RemoteAddr & 0xFF);
             * header[2] = (byte)(_socket.RemoteAddr >> 8 & 0xFF);
             * header[3] = (byte)(_socket.RemoteAddr >> 16 & 0xFF);
             * header[4] = (byte)(_socket.RemoteAddr >> 24);
             * header[5] = (byte)(_socket.RemotePort >> 8);
             * header[6] = (byte)(_socket.RemotePort & 0xFF);
             */
            string domain = DnsProxyServer.Lookup(_socket.RemoteAddr);

            if (domain == null)
            {
                Debug.WriteLine("Cannot find DNS record");
                DisconnectRemote();
                Reset();
                return;
            }
            byte[] firstSeg       = null;
            int    headerLen      = domain.Length + 4;
            int    bytesToConfirm = 0;

            if (localbuf.TryDequeue(out var firstBuf))
            {
                bytesToConfirm = firstBuf.Length;
                firstSeg       = new byte[headerLen + firstBuf.Length];
                Array.Copy(firstBuf, 0, firstSeg, headerLen, firstBuf.Length);
            }
            else
            {
                firstSeg = new byte[headerLen];
            }
            firstSeg[0] = 0x03;
            firstSeg[1] = (byte)domain.Length;
            Encoding.ASCII.GetBytes(domain).CopyTo(firstSeg, 2);
            firstSeg[headerLen - 2] = (byte)(_socket.RemotePort >> 8);
            firstSeg[headerLen - 1] = (byte)(_socket.RemotePort & 0xFF);
            var(encryptedFirstSeg, encryptedFirstSegLen) = Encrypt(firstSeg, (uint)firstSeg.Length);

            try
            {
                await networkStream.WriteAsync(encryptedFirstSeg, 0, (int)encryptedFirstSegLen);

                while (localbuf.TryDequeue(out var buf))
                {
                    bytesToConfirm += buf.Length;
                    // await networkWriteStream.WriteAsync(await Encrypt(buf));
                    var(data, len) = Encrypt(buf, (uint)buf.Length);
                    await networkStream.WriteAsync(data, 0, (int)len);
                }
                remoteConnected = true;
                Recved((ushort)bytesToConfirm);
                //await networkWriteStream.FlushAsync();
                Debug.WriteLine("Sent data with header");
            }
            catch (Exception)
            {
                Debug.WriteLine("Error sending header to remote");
                DisconnectRemote();
                Reset();
                return;
            }

            // IBuffer remotebuf = WindowsRuntimeBuffer.Create(RECV_BUFFER_LEN);
            byte[] remotebuf = new byte[RECV_BUFFER_LEN];
            while (r.Connected && networkStream.CanRead)
            {
                try
                {
                    var len = await networkStream.ReadAsync(remotebuf, 0, RECV_BUFFER_LEN).ConfigureAwait(false);

                    if (len == 0)
                    {
                        break;
                    }
#if YTLOG_VERBOSE
                    Debug.WriteLine($"Received {len} bytes");
#endif

                    await RemoteReceived(Decrypt(remotebuf, (uint)len));
                }
                catch (Exception)
                {
                    break;
                }
            }

            try
            {
                Debug.WriteLine("Remote sent no data");
                // networkReadStream?.Dispose();
                r?.Client?.Shutdown(SocketShutdown.Receive);
                Close();
            }
            catch (Exception) { }
        }
Пример #5
0
        public async void Init(string hashedPassword)
        {
            try
            {
                await r.ConnectAsync(server, port);

                // TODO: verify certificate
                // TODO: compile first
                // networkStream = new SslStream(r.GetStream(), false, new RemoteCertificateValidationCallback((a, b, c, d) => true));
                // await networkStream.AuthenticateAsClientAsync(server);
            }
            catch (Exception)
            {
                Debug.WriteLine("Error connecting to remote");
                DisconnectRemote();
                Reset();
                return;
            }
            Debug.WriteLine("Connected");
            string domain = DnsProxyServer.Lookup(_socket.RemoteAddr);

            if (domain == null)
            {
                Debug.WriteLine("Cannot find DNS record");
                DisconnectRemote();
                Reset();
                return;
            }
            byte[] firstSeg       = null;
            int    headerLen      = domain.Length + 65;
            int    bytesToConfirm = 0;

            if (localbuf.TryDequeue(out var firstBuf))
            {
                bytesToConfirm = firstBuf.Length;
                firstSeg       = new byte[headerLen + firstBuf.Length];
                Array.Copy(firstBuf, 0, firstSeg, headerLen, firstBuf.Length);
            }
            else
            {
                firstSeg = new byte[headerLen];
            }
            Encoding.UTF8.GetBytes(hashedPassword).CopyTo(firstSeg.AsSpan()); // hex(SHA224(password))
            firstSeg[56] = 0x0D;                                              // CR
            firstSeg[57] = 0x0A;                                              // LF
            firstSeg[58] = 0x01;                                              //  CMD
            firstSeg[59] = 0x03;                                              //  ATYP
            firstSeg[60] = (byte)domain.Length;                               // DST.ADDR length
            Encoding.ASCII.GetBytes(domain).CopyTo(firstSeg, 61);
            firstSeg[headerLen - 4] = (byte)(_socket.RemotePort >> 8);
            firstSeg[headerLen - 3] = (byte)(_socket.RemotePort & 0xFF);
            firstSeg[headerLen - 2] = 0x0D;
            firstSeg[headerLen - 1] = 0x0A;
            await networkStream.WriteAsync(firstSeg, 0, firstSeg.Length);

            try
            {
                while (localbuf.TryDequeue(out var buf))
                {
                    bytesToConfirm += buf.Length;
                    await networkStream.WriteAsync(buf, 0, buf.Length);
                }
                remoteConnected = true;
                Recved((ushort)bytesToConfirm);
                Debug.WriteLine("Sent data with header");
            }
            catch (Exception)
            {
                Debug.WriteLine("Error sending header to remote");
                DisconnectRemote();
                Reset();
                return;
            }

            byte[] remotebuf = new byte[RECV_BUFFER_LEN];
            while (r.Connected && networkStream.CanRead)
            {
                try
                {
                    var len = await networkStream.ReadAsync(remotebuf, 0, RECV_BUFFER_LEN).ConfigureAwait(false);

                    if (len == 0)
                    {
                        break;
                    }
#if YTLOG_VERBOSE
                    Debug.WriteLine($"Received {len} bytes");
#endif

                    await RemoteReceived(remotebuf.AsMemory(0, len));
                }
                catch (Exception)
                {
                    break;
                }
            }

            try
            {
                Debug.WriteLine("Remote sent no data");
                r?.Client?.Shutdown(SocketShutdown.Receive);
                Close();
            }
            catch (Exception) { }
        }
Пример #6
0
        public async void Init()
        {
            var connectTask = r.ConnectAsync(server, port);

            Debug.WriteLine("Connected");
            string domain = DnsProxyServer.Lookup(_socket.RemoteAddr);

            if (domain == null)
            {
                Debug.WriteLine("Cannot find DNS record");
                DisconnectRemote();
                Reset();
                return;
            }
            string portStr = _socket.RemotePort.ToString();

            byte[] portBytes   = Encoding.UTF8.GetBytes(portStr);
            byte[] domainBytes = Encoding.UTF8.GetBytes(domain);
            int    headerLen   = HEADER1.Length + domainBytes.Length + 1 + portBytes.Length + HEADER2.Length;

            byte[] firstSeg = new byte[headerLen];
            HEADER1.CopyTo(firstSeg, 0);
            domainBytes.CopyTo(firstSeg, HEADER1.Length);
            firstSeg[HEADER1.Length + domainBytes.Length] = (byte)':';
            portBytes.CopyTo(firstSeg, HEADER1.Length + domainBytes.Length + 1);
            HEADER2.CopyTo(firstSeg, headerLen - HEADER2.Length);

            try
            {
                await connectTask;
                networkStream = r.GetStream();
                await networkStream.WriteAsync(firstSeg, 0, headerLen);

                byte[] responseBuf = new byte[RECV_BUFFER_LEN];
                var    responseLen = await networkStream.ReadAsync(responseBuf, 0, 100);

                if (responseLen < 14)
                {
                    throw new InvalidOperationException("Remote response too short.");
                }
                if ((responseBuf[9] == (byte)'2') && (responseBuf[10] == (byte)'0') && (responseBuf[11] == (byte)'0'))
                {
                    // 200 objk
                }
                else
                {
                    throw new InvalidOperationException("Remote connection cannot be established.");
                }
                bool foundHeader = false;
                int  headerStart;
                for (headerStart = 12; headerStart < responseLen - 3; headerStart++)
                {
                    if (responseBuf[headerStart] == '\r')
                    {
                        if (responseBuf[headerStart + 1] == '\n')
                        {
                            if (responseBuf[headerStart + 2] == '\r')
                            {
                                if (responseBuf[headerStart + 3] == '\n')
                                {
                                    foundHeader = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (!foundHeader)
                {
                    throw new InvalidOperationException("Unrecognized remote header.");
                }
                headerStart += 4;
                if (headerStart >= responseLen)
                {
                    // No initial data
                }
                else
                {
                    await RemoteReceived(responseBuf.AsMemory(headerStart, responseLen));
                }

                int bytesToConfirm = 0;
                while (localbuf.TryDequeue(out var buf))
                {
                    bytesToConfirm += buf.Length;
                    // await networkWriteStream.WriteAsync(await Encrypt(buf));
                    await networkStream.WriteAsync(buf, 0, buf.Length);
                }
                remoteConnected = true;
                if (bytesToConfirm > 0)
                {
                    Recved((ushort)bytesToConfirm);
                }
                //await networkWriteStream.FlushAsync();
                Debug.WriteLine("Sent data with header");
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error sending header to remote" + ex.Message);
                DisconnectRemote();
                Reset();
                return;
            }

            // IBuffer remotebuf = WindowsRuntimeBuffer.Create(RECV_BUFFER_LEN);
            byte[] remotebuf = new byte[RECV_BUFFER_LEN];
            while (r.Connected && networkStream.CanRead)
            {
                try
                {
                    var len = await networkStream.ReadAsync(remotebuf, 0, RECV_BUFFER_LEN).ConfigureAwait(false);

                    if (len == 0)
                    {
                        break;
                    }
#if YTLOG_VERBOSE
                    Debug.WriteLine($"Received {len} bytes");
#endif

                    await RemoteReceived(remotebuf.AsMemory(0, len));
                }
                catch (Exception)
                {
                    break;
                }
            }

            try
            {
                Debug.WriteLine("Remote sent no data");
                // networkReadStream?.Dispose();
                r?.Client?.Shutdown(SocketShutdown.Receive);
                Close();
            }
            catch (Exception) { }
        }