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(); } }
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(); } }
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(); } }
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(); } }