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