diff --git a/shadowsocks-csharp/Controller/Service/Listener.cs b/shadowsocks-csharp/Controller/Service/Listener.cs index 8b7a48d8..70819163 100644 --- a/shadowsocks-csharp/Controller/Service/Listener.cs +++ b/shadowsocks-csharp/Controller/Service/Listener.cs @@ -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) diff --git a/shadowsocks-csharp/Controller/Service/PortForwarder.cs b/shadowsocks-csharp/Controller/Service/PortForwarder.cs index 46ec9733..1acfa5bd 100644 --- a/shadowsocks-csharp/Controller/Service/PortForwarder.cs +++ b/shadowsocks-csharp/Controller/Service/PortForwarder.cs @@ -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(); diff --git a/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs b/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs index 0258087c..187e7a09 100644 --- a/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs @@ -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(); diff --git a/shadowsocks-csharp/Controller/Service/UDPRelay.cs b/shadowsocks-csharp/Controller/Service/UDPRelay.cs index 5367e29a..5ac03839 100644 --- a/shadowsocks-csharp/Controller/Service/UDPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/UDPRelay.cs @@ -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]; diff --git a/shadowsocks-csharp/Data/privoxy_conf.txt b/shadowsocks-csharp/Data/privoxy_conf.txt index a75aa56c..bef1c726 100644 --- a/shadowsocks-csharp/Data/privoxy_conf.txt +++ b/shadowsocks-csharp/Data/privoxy_conf.txt @@ -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