| @@ -27,9 +27,14 @@ namespace Shadowsocks.Controller | |||
| public class UDPState | |||
| { | |||
| public UDPState(Socket s) | |||
| { | |||
| socket = s; | |||
| remoteEndPoint = new IPEndPoint(s.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0); | |||
| } | |||
| public Socket socket; | |||
| public byte[] buffer = new byte[4096]; | |||
| public EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); | |||
| public EndPoint remoteEndPoint; | |||
| } | |||
| Configuration _config; | |||
| @@ -60,14 +65,14 @@ namespace Shadowsocks.Controller | |||
| try | |||
| { | |||
| // Create a TCP/IP socket. | |||
| _tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); | |||
| _udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |||
| _tcpSocket = new Socket(config.isIPv6Enabled ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); | |||
| _udpSocket = new Socket(config.isIPv6Enabled ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |||
| _tcpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); | |||
| _udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); | |||
| IPEndPoint localEndPoint = null; | |||
| localEndPoint = _shareOverLAN | |||
| ? new IPEndPoint(IPAddress.Any, _config.localPort) | |||
| : new IPEndPoint(IPAddress.Loopback, _config.localPort); | |||
| ? new IPEndPoint(config.isIPv6Enabled ? IPAddress.IPv6Any : IPAddress.Any, _config.localPort) | |||
| : new IPEndPoint(config.isIPv6Enabled ? IPAddress.IPv6Loopback : IPAddress.Loopback, _config.localPort); | |||
| // Bind the socket to the local endpoint and listen for incoming connections. | |||
| _tcpSocket.Bind(localEndPoint); | |||
| @@ -81,8 +86,7 @@ namespace Shadowsocks.Controller | |||
| Logging.Info(Encryption.EncryptorFactory.DumpRegisteredEncryptor()); | |||
| } | |||
| _tcpSocket.BeginAccept(new AsyncCallback(AcceptCallback), _tcpSocket); | |||
| UDPState udpState = new UDPState(); | |||
| udpState.socket = _udpSocket; | |||
| UDPState udpState = new UDPState(_udpSocket); | |||
| _udpSocket.BeginReceiveFrom(udpState.buffer, 0, udpState.buffer.Length, 0, ref udpState.remoteEndPoint, new AsyncCallback(RecvFromCallback), udpState); | |||
| } | |||
| catch (SocketException) | |||
| @@ -105,7 +109,7 @@ namespace Shadowsocks.Controller | |||
| _udpSocket = null; | |||
| } | |||
| _services.ForEach(s=>s.Stop()); | |||
| _services.ForEach(s => s.Stop()); | |||
| } | |||
| public void RecvFromCallback(IAsyncResult ar) | |||
| @@ -49,7 +49,8 @@ namespace Shadowsocks.Controller | |||
| _local = socket; | |||
| try | |||
| { | |||
| EndPoint remoteEP = SocketUtil.GetEndPoint("127.0.0.1", targetPort); | |||
| // Local Port Forward use IP as is | |||
| EndPoint remoteEP = SocketUtil.GetEndPoint(_local.AddressFamily == AddressFamily.InterNetworkV6 ? "[::1]" : "127.0.0.1", targetPort); | |||
| // Connect to the remote endpoint. | |||
| _remote = new WrappedSocket(); | |||
| @@ -49,10 +49,14 @@ namespace Shadowsocks.Controller | |||
| KillProcess(p); | |||
| } | |||
| string privoxyConfig = Resources.privoxy_conf; | |||
| _runningPort = GetFreePort(); | |||
| _runningPort = GetFreePort(configuration.isIPv6Enabled); | |||
| privoxyConfig = privoxyConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString()); | |||
| privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_PORT__", _runningPort.ToString()); | |||
| privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); | |||
| privoxyConfig = configuration.isIPv6Enabled | |||
| ? privoxyConfig.Replace("__PRIVOXY_BIND_IP__", configuration.shareOverLan ? "[::]" : "[::1]") | |||
| .Replace("__SOCKS_HOST__", "[::1]") | |||
| : privoxyConfig.Replace("__PRIVOXY_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1") | |||
| .Replace("__SOCKS_HOST__", "127.0.0.1"); | |||
| FileManager.ByteArrayToFile(Utils.GetTempPath(_uniqueConfigFile), Encoding.UTF8.GetBytes(privoxyConfig)); | |||
| _process = new Process | |||
| @@ -140,13 +144,13 @@ namespace Shadowsocks.Controller | |||
| } | |||
| } | |||
| private int GetFreePort() | |||
| private int GetFreePort(bool isIPv6 = false) | |||
| { | |||
| int defaultPort = 8123; | |||
| try | |||
| { | |||
| // TCP stack please do me a favor | |||
| TcpListener l = new TcpListener(IPAddress.Loopback, 0); | |||
| TcpListener l = new TcpListener(isIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0); | |||
| l.Start(); | |||
| var port = ((IPEndPoint)l.LocalEndpoint).Port; | |||
| l.Stop(); | |||
| @@ -58,6 +58,19 @@ namespace Shadowsocks.Controller | |||
| private IPEndPoint _localEndPoint; | |||
| private IPEndPoint _remoteEndPoint; | |||
| private IPAddress GetIPAddress() | |||
| { | |||
| switch (_remote.AddressFamily) | |||
| { | |||
| case AddressFamily.InterNetwork: | |||
| return IPAddress.Any; | |||
| case AddressFamily.InterNetworkV6: | |||
| return IPAddress.IPv6Any; | |||
| default: | |||
| return IPAddress.Any; | |||
| } | |||
| } | |||
| public UDPHandler(Socket local, Server server, IPEndPoint localEndPoint) | |||
| { | |||
| _local = local; | |||
| @@ -74,7 +87,7 @@ namespace Shadowsocks.Controller | |||
| } | |||
| _remoteEndPoint = new IPEndPoint(ipAddress, server.server_port); | |||
| _remote = new Socket(_remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); | |||
| _remote.Bind(new IPEndPoint(IPAddress.Any, 0)); | |||
| _remote.Bind(new IPEndPoint(GetIPAddress(), 0)); | |||
| } | |||
| public void Send(byte[] data, int length) | |||
| @@ -91,7 +104,7 @@ namespace Shadowsocks.Controller | |||
| public void Receive() | |||
| { | |||
| EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); | |||
| EndPoint remoteEndPoint = new IPEndPoint(GetIPAddress(), 0); | |||
| Logging.Debug($"++++++Receive Server Port, size:" + _buffer.Length); | |||
| _remote?.BeginReceiveFrom(_buffer, 0, _buffer.Length, 0, ref remoteEndPoint, new AsyncCallback(RecvFromCallback), null); | |||
| } | |||
| @@ -101,7 +114,7 @@ namespace Shadowsocks.Controller | |||
| try | |||
| { | |||
| if (_remote == null) return; | |||
| EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); | |||
| EndPoint remoteEndPoint = new IPEndPoint(GetIPAddress(), 0); | |||
| int bytesRead = _remote.EndReceiveFrom(ar, ref remoteEndPoint); | |||
| byte[] dataOut = new byte[bytesRead]; | |||
| @@ -3,6 +3,6 @@ toggle 0 | |||
| logfile ss_privoxy.log | |||
| show-on-task-bar 0 | |||
| activity-animation 0 | |||
| forward-socks5 / 127.0.0.1:__SOCKS_PORT__ . | |||
| forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . | |||
| max-client-connections 2048 | |||
| hide-console | |||