Пример #1
0
            private void Connect()
            {
                try
                {
                    IPAddress ipAddress   = null;
                    int       _targetPort = 0;
                    {
                        if (_firstPacket[0] == 1)
                        {
                            byte[] addr = new byte[4];
                            Array.Copy(_firstPacket, 1, addr, 0, addr.Length);
                            ipAddress    = new IPAddress(addr);
                            _targetPort  = (_firstPacket[5] << 8) | _firstPacket[6];
                            _remote_host = ipAddress.ToString();
                            Logging.Info((_local_proxy ? "Local proxy" : "Direct") + " connect " + _remote_host + ":" + _targetPort.ToString());
                        }
                        else if (_firstPacket[0] == 4)
                        {
                            byte[] addr = new byte[16];
                            Array.Copy(_firstPacket, 1, addr, 0, addr.Length);
                            ipAddress    = new IPAddress(addr);
                            _targetPort  = (_firstPacket[17] << 8) | _firstPacket[18];
                            _remote_host = ipAddress.ToString();
                            Logging.Info((_local_proxy ? "Local proxy" : "Direct") + " connect " + _remote_host + ":" + _targetPort.ToString());
                        }
                        else if (_firstPacket[0] == 3)
                        {
                            int    len  = _firstPacket[1];
                            byte[] addr = new byte[len];
                            Array.Copy(_firstPacket, 2, addr, 0, addr.Length);
                            _remote_host = Encoding.UTF8.GetString(_firstPacket, 2, len);
                            _targetPort  = (_firstPacket[len + 2] << 8) | _firstPacket[len + 3];
                            Logging.Info((_local_proxy ? "Local proxy" : "Direct") + " connect " + _remote_host + ":" + _targetPort.ToString());

                            //if (!_local_proxy)
                            {
                                if (!IPAddress.TryParse(_remote_host, out ipAddress))
                                {
                                    if (_config.proxyRuleMode == (int)ProxyRuleMode.UserCustom)
                                    {
                                        Shadowsocks.Model.HostMap hostMap = HostMap.Instance();
                                        string host_addr;
                                        if (hostMap.GetHost(_remote_host, out host_addr))
                                        {
                                            if (!String.IsNullOrEmpty(host_addr))
                                            {
                                                string lower_host_addr = host_addr.ToLower();
                                                if (lower_host_addr.StartsWith("reject"))
                                                {
                                                    Close();
                                                    return;
                                                }
                                                else if (lower_host_addr.IndexOf('.') >= 0 || lower_host_addr.IndexOf(':') >= 0)
                                                {
                                                    if (!IPAddress.TryParse(lower_host_addr, out ipAddress))
                                                    {
                                                        //
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (ipAddress == null)
                                    {
                                        ipAddress = Utils.DnsBuffer.Get(_remote_host);
                                    }
                                }
                                if (ipAddress == null)
                                {
                                    if (_remote_host.IndexOf('.') >= 0)
                                    {
                                        ipAddress = Util.Utils.QueryDns(_remote_host, _config.dnsServer);
                                    }
                                    else
                                    {
                                        ipAddress = Utils.QueryDns(_remote_host, null);
                                    }
                                }
                                if (ipAddress != null)
                                {
                                    Utils.DnsBuffer.Set(_remote_host, new IPAddress(ipAddress.GetAddressBytes()));
                                    Utils.DnsBuffer.Sweep();
                                }
                                else
                                {
                                    if (!_local_proxy)
                                    {
                                        throw new SocketException((int)SocketError.HostNotFound);
                                    }
                                }
                            }
                        }
                        _remote_port = _targetPort;
                    }
                    if (ipAddress != null && _config.proxyRuleMode == (int)ProxyRuleMode.UserCustom)
                    {
                        Shadowsocks.Model.HostMap hostMap = HostMap.Instance();
                        string host_addr;
                        if (hostMap.GetIP(ipAddress, out host_addr))
                        {
                            string lower_host_addr = host_addr.ToLower();
                            if (lower_host_addr.StartsWith("reject")
                                )
                            {
                                Close();
                                return;
                            }
                        }
                    }
                    if (_local_proxy)
                    {
                        IPAddress.TryParse(_config.proxyHost, out ipAddress);
                        _targetPort = _config.proxyPort;
                    }
                    // ProxyAuth recv only socks5 head, so don't need to save anything else
                    IPEndPoint remoteEP = new IPEndPoint(ipAddress, _targetPort);

                    _remote = new ProxySocketTun(ipAddress.AddressFamily,
                                                 SocketType.Stream, ProtocolType.Tcp);
                    _remote.GetSocket().NoDelay = true;

                    // Connect to the remote endpoint.
                    _remote.BeginConnect(remoteEP,
                                         new AsyncCallback(ConnectCallback), null);
                }
                catch (Exception e)
                {
                    Logging.LogUsefulException(e);
                    Close();
                }
            }
Пример #2
0
        private void ProxyConnectCallback(IAsyncResult ar)
        {
            if (_closed)
            {
                return;
            }
            try
            {
                var        session      = (AsyncSession <ProxyTimer>)ar.AsyncState;
                ProxyTimer timer        = session.State;
                var        destEndPoint = timer.DestEndPoint;
                var        server       = timer.Server;
                timer.Elapsed -= ProxyConnectTimer_Elapsed;
                timer.Enabled  = false;
                timer.Dispose();

                var remote = session.Remote;

                // Complete the connection.
                remote.EndConnectProxy(ar);

                _proxyConnected = true;

                if (_config.isVerboseLogging)
                {
                    if (!(remote is DirectConnect))
                    {
                        Logging.Info($"Socket connected to proxy {remote.ProxyEndPoint}");
                    }
                }

                _startConnectTime = DateTime.Now;
                ServerTimer connectTimer = new ServerTimer(_serverTimeout)
                {
                    AutoReset = false
                };
                connectTimer.Elapsed += DestConnectTimer_Elapsed;
                connectTimer.Enabled  = true;
                connectTimer.Session  = session;
                connectTimer.Server   = server;

                _destConnected = false;

                NetworkCredential auth = null;
                if (_config.proxy.useAuth)
                {
                    auth = new NetworkCredential(_config.proxy.authUser, _config.proxy.authPwd);
                }

                // Connect to the remote endpoint.
                remote.BeginConnectDest(destEndPoint, ConnectCallback,
                                        new AsyncSession <ServerTimer>(session, connectTimer), auth);
            }
            catch (ArgumentException)
            {
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                Close();
            }
        }
Пример #3
0
        private void PipeConnectionReceiveCallback(IAsyncResult ar)
        {
            if (_closed)
            {
                return;
            }
            try
            {
                if (connection == null)
                {
                    return;
                }
                int bytesRead = connection.EndReceive(ar);
                _totalWrite += bytesRead;

                var session = (AsyncSession <bool>)ar.AsyncState;
                var remote  = session.Remote;

                if (bytesRead > 0)
                {
                    /*
                     * Only the first packet contains the socks5 header, it doesn't make sense to parse every packets.
                     * Also it's unnecessary to parse these data if we turn off the VerboseLogging.
                     */
                    if (session.State && _config.isVerboseLogging)
                    {
                        int    atyp = _connetionRecvBuffer[0];
                        string dst_addr;
                        int    dst_port;
                        switch (atyp)
                        {
                        case 1:     // IPv4 address, 4 bytes
                            dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
                            dst_port = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];

                            Logging.Info($"connect to {dst_addr}:{dst_port}");
                            session.State = false;
                            break;

                        case 3:     // domain name, length + str
                            int len = _connetionRecvBuffer[1];
                            dst_addr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
                            dst_port = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];

                            Logging.Info($"connect to {dst_addr}:{dst_port}");
                            session.State = false;
                            break;

                        case 4:     // IPv6 address, 16 bytes
                            dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray()).ToString();
                            dst_port = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];

                            Logging.Info($"connect to [{dst_addr}]:{dst_port}");
                            session.State = false;
                            break;
                        }
                    }

                    int bytesToSend;
                    lock (_encryptionLock)
                    {
                        if (_closed)
                        {
                            return;
                        }
                        encryptor.Encrypt(_connetionRecvBuffer, bytesRead, _connetionSendBuffer, out bytesToSend);
                    }
                    _tcprelay.UpdateOutboundCounter(server, bytesToSend);
                    _startSendingTime = DateTime.Now;
                    _bytesToSend      = bytesToSend;
                    remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), session);
                    IStrategy strategy = controller.GetCurrentStrategy();
                    strategy?.UpdateLastWrite(server);
                }
                else
                {
                    remote.Shutdown(SocketShutdown.Send);
                    _remoteShutdown = true;
                    CheckClose();
                }
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                Close();
            }
        }
Пример #4
0
        private void OnAddressFullyRead(IAsyncResult ar)
        {
            if (_closed)
            {
                return;
            }
            try
            {
                int bytesRead = _connection.EndReceive(ar);

                var states = (object[])ar.AsyncState;

                int bytesRemain = (int)states[0];
                var onSuccess   = (Action)states[1];

                if (bytesRead >= bytesRemain)
                {
                    _firstPacketLength = bytesRead + 2;

                    int atyp = _connetionRecvBuffer[0];

                    string dstAddr = "Unknown";
                    int    dstPort = -1;
                    switch (atyp)
                    {
                    case ATYP_IPv4:     // IPv4 address, 4 bytes
                        dstAddr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
                        dstPort = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];

                        _addrBufLength = ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
                        break;

                    case ATYP_DOMAIN:     // domain name, length + str
                        int len = _connetionRecvBuffer[1];
                        dstAddr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
                        dstPort = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];

                        _addrBufLength = ADDR_ATYP_LEN + 1 + len + ADDR_PORT_LEN;
                        break;

                    case ATYP_IPv6:     // IPv6 address, 16 bytes
                        dstAddr = $"[{new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray())}]";
                        dstPort = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];

                        _addrBufLength = ADDR_ATYP_LEN + 16 + ADDR_PORT_LEN;
                        break;
                    }

                    if (_config.isVerboseLogging)
                    {
                        Logging.Info($"connect to {dstAddr}:{dstPort}");
                    }

                    _destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort);

                    onSuccess.Invoke(); /* StartConnect() */
                }
                else
                {
                    Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()");
                    Close();
                }
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
                Close();
            }
        }