From f8d8f27c40ce628559b407cef9485f1e69ae7b9b Mon Sep 17 00:00:00 2001 From: BreakWa11 Date: Mon, 17 Oct 2016 09:34:42 +0800 Subject: [PATCH] 3.9.6 --- .gitignore | 1 + shadowsocks-csharp/Controller/APIServer.cs | 13 +- .../Controller/HttpPortForwarder.cs | 1 - shadowsocks-csharp/Controller/Local.cs | 137 +++--- shadowsocks-csharp/Controller/PACServer.cs | 59 +-- shadowsocks-csharp/Controller/ProxyAuth.cs | 7 +- shadowsocks-csharp/Controller/ProxySocket.cs | 426 +++++++++++++++++- .../Controller/ShadowsocksController.cs | 19 +- .../Controller/Socks5Forwarder.cs | 281 ++++++------ shadowsocks-csharp/Controller/SystemProxy.cs | 4 +- .../Controller/UpdateChecker.cs | 2 +- shadowsocks-csharp/Data/cn.txt | 4 +- shadowsocks-csharp/Data/zh-tw.txt | 4 +- shadowsocks-csharp/Model/Configuration.cs | 74 ++- shadowsocks-csharp/Model/IPRangeSet.cs | 91 ++++ shadowsocks-csharp/Model/Server.cs | 105 ++++- shadowsocks-csharp/Util/Util.cs | 75 +++ .../View/ConfigForm.Designer.cs | 3 +- shadowsocks-csharp/View/ConfigForm.cs | 22 +- shadowsocks-csharp/View/MenuViewController.cs | 29 +- .../View/QRCodeForm.Designer.cs | 70 --- shadowsocks-csharp/View/QRCodeForm.cs | 60 --- shadowsocks-csharp/View/QRCodeForm.resx | 120 ----- .../View/SettingsForm.Designer.cs | 47 +- .../View/ShowTextForm.Designer.cs | 3 +- shadowsocks-csharp/View/ShowTextForm.cs | 3 +- .../shadowsocks-csharp-console.csproj | 1 + shadowsocks-csharp/shadowsocks-csharp.csproj | 10 +- .../shadowsocks-csharp4.0.csproj | 10 +- 29 files changed, 1086 insertions(+), 595 deletions(-) create mode 100644 shadowsocks-csharp/Model/IPRangeSet.cs delete mode 100755 shadowsocks-csharp/View/QRCodeForm.Designer.cs delete mode 100755 shadowsocks-csharp/View/QRCodeForm.cs delete mode 100755 shadowsocks-csharp/View/QRCodeForm.resx diff --git a/.gitignore b/.gitignore index 2bef8a0..67047e4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ TestResults *.user *.exe +/templates diff --git a/shadowsocks-csharp/Controller/APIServer.cs b/shadowsocks-csharp/Controller/APIServer.cs index daaaafa..e13c90b 100644 --- a/shadowsocks-csharp/Controller/APIServer.cs +++ b/shadowsocks-csharp/Controller/APIServer.cs @@ -49,13 +49,16 @@ public bool Handle(byte[] firstPacket, int length, Socket socket) } else if (kv.Length == 1) { - if (line.IndexOf("api?") > 0) + if (line.IndexOf("auth=" + _config.localAuthPassword) > 0) { - req = line.Substring(line.IndexOf("api?") + 4); - if (line.IndexOf("GET ") == 0 || line.IndexOf("POST ") == 0) + if (line.IndexOf(" /api?") > 0) { - pathMatch = true; - req = req.Substring(0, req.IndexOf(" ")); + req = line.Substring(line.IndexOf("api?") + 4); + if (line.IndexOf("GET ") == 0 || line.IndexOf("POST ") == 0) + { + pathMatch = true; + req = req.Substring(0, req.IndexOf(" ")); + } } } } diff --git a/shadowsocks-csharp/Controller/HttpPortForwarder.cs b/shadowsocks-csharp/Controller/HttpPortForwarder.cs index 8fd2358..bd64cff 100644 --- a/shadowsocks-csharp/Controller/HttpPortForwarder.cs +++ b/shadowsocks-csharp/Controller/HttpPortForwarder.cs @@ -166,7 +166,6 @@ private void Connect() { try { - // TODO async resolving IPAddress ipAddress; bool parsed = IPAddress.TryParse("127.0.0.1", out ipAddress); IPEndPoint remoteEP = new IPEndPoint(ipAddress, _targetPort); diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index f2e2bc6..523d66e 100644 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -9,6 +9,7 @@ using System.Timers; using System.Threading; using OpenDNS; +using Shadowsocks.Util; namespace Shadowsocks.Controller { @@ -55,10 +56,13 @@ class Local : Listener.Service { private Configuration _config; private ServerTransferTotal _transfer; - public Local(Configuration config, ServerTransferTotal transfer) + private IPRangeSet _IPRange; + + public Local(Configuration config, ServerTransferTotal transfer, IPRangeSet IPRange) { - this._config = config; - this._transfer = transfer; + _config = config; + _transfer = transfer; + _IPRange = IPRange; } protected bool Accept(byte[] firstPacket, int length) @@ -93,7 +97,7 @@ public bool Handle(byte[] firstPacket, int length, Socket socket) { return false; } - new ProxyAuthHandler(_config, _transfer, firstPacket, length, socket); + new ProxyAuthHandler(_config, _transfer, _IPRange, firstPacket, length, socket); return true; } } @@ -142,9 +146,8 @@ class Handler protected ProtocolResponseDetector detector = new ProtocolResponseDetector(); // remote socket. //protected Socket remote; - protected ProxySocket remote; - protected ProxySocket remoteUDP; - protected DnsQuery dns; + protected ProxyEncryptSocket remote; + protected ProxyEncryptSocket remoteUDP; // Size of receive buffer. protected const int RecvSize = 4096; protected const int BufferSize = 16384; @@ -257,7 +260,7 @@ private void timer_Elapsed(object sender, ElapsedEventArgs e) try { - if (cfg.try_keep_alive <= 0 && State == ConnectState.CONNECTED && remote != null && remote.CanSendKeepAlive) + if (cfg.try_keep_alive <= 0 && State == ConnectState.CONNECTED && remote != null && remoteUDP == null && remote.CanSendKeepAlive) { cfg.try_keep_alive++; RemoteSendWithoutCallback(null, -1); @@ -528,7 +531,7 @@ private void BeginConnect(IPAddress ipAddress, int serverPort) || connectionUDP == null || connectionUDP != null && server.udp_over_tcp) { - remote = new ProxySocket(ipAddress.AddressFamily, + remote = new ProxyEncryptSocket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); remote.GetSocket().SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); try @@ -547,7 +550,7 @@ private void BeginConnect(IPAddress ipAddress, int serverPort) { try { - remoteUDP = new ProxySocket(ipAddress.AddressFamily, + remoteUDP = new ProxyEncryptSocket(ipAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); remoteUDP.GetSocket().Bind(new IPEndPoint(ipAddress.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0)); @@ -648,13 +651,13 @@ private void CloseSocket(ref Socket sock) } } - private void CloseSocket(ref ProxySocket sock) + private void CloseSocket(ref ProxyEncryptSocket sock) { lock (this) { if (sock != null) { - ProxySocket s = sock; + ProxyEncryptSocket s = sock; sock = null; try { @@ -783,72 +786,6 @@ private bool ConnectProxyServer(string strRemoteHost, int iRemotePort) } } - private IPAddress QueryDns(string host, string dns_servers) - { - IPAddress ipAddress; - bool parsed = IPAddress.TryParse(host, out ipAddress); - if (!parsed) - { - if (server.DnsBuffer().isExpired(host)) - { - if (dns_servers != null && dns_servers.Length > 0) - { - OpenDNS.Types[] types; - //if (false) - // types = new Types[] { Types.AAAA, Types.A }; - //else - types = new Types[] { Types.A, Types.AAAA }; - string[] dns_server = dns_servers.Split(','); - for (int query_i = 0; query_i < types.Length; ++query_i) - { - dns = new DnsQuery(host, types[query_i]); - dns.RecursionDesired = true; - foreach (string server in dns_server) - { - dns.Servers.Add(server); - } - if (dns.Send()) - { - int count = dns.Response.Answers.Count; - if (count > 0) - { - for (int i = 0; i < count; ++i) - { - if (((ResourceRecord)dns.Response.Answers[i]).Type != types[query_i]) - continue; - return ((OpenDNS.Address)dns.Response.Answers[i]).IP; - } - } - } - } - } - { - try - { - GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry); - IAsyncResult result = callback.BeginInvoke(host, null, null); - if (result.AsyncWaitHandle.WaitOne(5, false)) - { - foreach(IPAddress ad in callback.EndInvoke(result).AddressList) - { - return ad; - //if (ad.AddressFamily == AddressFamily.InterNetwork) - //{ - // return ad; - //} - } - } - } - catch - { - - } - } - } - } - return ipAddress; - } - private void Connect() { remote = null; @@ -876,13 +813,44 @@ private void Connect() ResetTimeout(cfg.TTL); if (cfg.fouce_local_dns_query && cfg.targetHost != null) { - IPAddress ipAddress = QueryDns(cfg.targetHost, cfg.dns_servers); + IPAddress ipAddress; + //if (server.DnsBuffer().isExpired(cfg.targetHost)) + //{ + // ipAddress = Util.Utils.QueryDns(cfg.targetHost, cfg.dns_servers); + //} + //else + //{ + // ipAddress = server.DnsBuffer().ip; + //} + //if (ipAddress != null) + //{ + // server.DnsBuffer().UpdateDns(cfg.targetHost, ipAddress); + // cfg.targetHost = ipAddress.ToString(); + // ResetTimeout(cfg.TTL); + //} + + string host = cfg.targetHost; + + if (!IPAddress.TryParse(host, out ipAddress)) + { + ipAddress = Utils.DnsBuffer.Get(host); + } + if (ipAddress == null) + { + ipAddress = Utils.QueryDns(host, cfg.dns_servers); + } if (ipAddress != null) { - server.DnsBuffer().UpdateDns(cfg.targetHost, ipAddress); + Utils.DnsBuffer.Set(host, ipAddress); + Utils.DnsBuffer.Sweep(); + cfg.targetHost = ipAddress.ToString(); ResetTimeout(cfg.TTL); } + else + { + //throw new SocketException((int)SocketError.HostNotFound); + } } lock (this) @@ -911,7 +879,14 @@ private void Connect() bool dns_ok = false; if (!dns_ok) { - ipAddress = QueryDns(serverURI, cfg.dns_servers); + if (server.DnsBuffer().isExpired(serverURI)) + { + ipAddress = Util.Utils.QueryDns(serverURI, cfg.dns_servers); + } + else + { + ipAddress = server.DnsBuffer().ip; + } if (ipAddress != null) { server.DnsBuffer().UpdateDns(serverURI, ipAddress); diff --git a/shadowsocks-csharp/Controller/PACServer.cs b/shadowsocks-csharp/Controller/PACServer.cs index 67673cd..890ba90 100755 --- a/shadowsocks-csharp/Controller/PACServer.cs +++ b/shadowsocks-csharp/Controller/PACServer.cs @@ -72,44 +72,47 @@ public bool Handle(byte[] firstPacket, int length, Socket socket) } else if (kv.Length == 1) { - if (line.IndexOf("pac") > 0 && line.IndexOf("GET") == 0) + if (line.IndexOf("auth=" + _config.localAuthPassword) > 0) { - string url = line.Substring(line.IndexOf(" ") + 1); - url = url.Substring(0, url.IndexOf(" ")); - pathMatch = true; - int port_pos = url.IndexOf("port="); - if (port_pos > 0) + if (line.IndexOf(" /pac?") > 0 && line.IndexOf("GET") == 0) { - string port = url.Substring(port_pos + 5); - if (port.IndexOf("&") >= 0) + string url = line.Substring(line.IndexOf(" ") + 1); + url = url.Substring(0, url.IndexOf(" ")); + pathMatch = true; + int port_pos = url.IndexOf("port="); + if (port_pos > 0) { - port = port.Substring(0, port.IndexOf("&")); - } + string port = url.Substring(port_pos + 5); + if (port.IndexOf("&") >= 0) + { + port = port.Substring(0, port.IndexOf("&")); + } - int ip_pos = url.IndexOf("ip="); - if (ip_pos > 0) - { - proxy = url.Substring(ip_pos + 3); - if (proxy.IndexOf("&") >= 0) + int ip_pos = url.IndexOf("ip="); + if (ip_pos > 0) { - proxy = proxy.Substring(0, proxy.IndexOf("&")); + proxy = url.Substring(ip_pos + 3); + if (proxy.IndexOf("&") >= 0) + { + proxy = proxy.Substring(0, proxy.IndexOf("&")); + } + proxy += ":" + port + ";"; } - proxy += ":" + port + ";"; + else + { + proxy = "127.0.0.1:" + port + ";"; + } + } + + if (url.IndexOf("type=socks4") > 0 || url.IndexOf("type=s4") > 0) + { + socksType = 4; } - else + if (url.IndexOf("type=socks5") > 0 || url.IndexOf("type=s5") > 0) { - proxy = "127.0.0.1:" + port + ";"; + socksType = 5; } } - - if (url.IndexOf("type=socks4") > 0 || url.IndexOf("type=s4") > 0) - { - socksType = 4; - } - if (url.IndexOf("type=socks5") > 0 || url.IndexOf("type=s5") > 0) - { - socksType = 5; - } } } } diff --git a/shadowsocks-csharp/Controller/ProxyAuth.cs b/shadowsocks-csharp/Controller/ProxyAuth.cs index 9cacd52..bfafdb0 100644 --- a/shadowsocks-csharp/Controller/ProxyAuth.cs +++ b/shadowsocks-csharp/Controller/ProxyAuth.cs @@ -24,7 +24,7 @@ class ProxyAuthHandler { private Configuration _config; private ServerTransferTotal _transfer; - + private IPRangeSet _IPRange; private byte[] _firstPacket; private int _firstPacketLength; @@ -40,12 +40,13 @@ class ProxyAuthHandler protected HttpPraser httpProxyState; - public ProxyAuthHandler(Configuration config, ServerTransferTotal transfer, byte[] firstPacket, int length, Socket socket) + public ProxyAuthHandler(Configuration config, ServerTransferTotal transfer, IPRangeSet IPRange, byte[] firstPacket, int length, Socket socket) { int local_port = ((IPEndPoint)socket.LocalEndPoint).Port; _config = config; _transfer = transfer; + _IPRange = IPRange; _firstPacket = firstPacket; _firstPacketLength = length; _connection = socket; @@ -527,7 +528,7 @@ private void Connect() } else { - if (_connectionUDP == null && new Socks5Forwarder(_config).Handle(_remoteHeaderSendBuffer, _remoteHeaderSendBuffer.Length, _connection)) + if (_connectionUDP == null && new Socks5Forwarder(_config, _IPRange).Handle(_remoteHeaderSendBuffer, _remoteHeaderSendBuffer.Length, _connection)) { return; } diff --git a/shadowsocks-csharp/Controller/ProxySocket.cs b/shadowsocks-csharp/Controller/ProxySocket.cs index 1a681ae..6b0f8bb 100644 --- a/shadowsocks-csharp/Controller/ProxySocket.cs +++ b/shadowsocks-csharp/Controller/ProxySocket.cs @@ -17,7 +17,429 @@ class CallbackState public object state; } - class ProxySocket + class ProxySocketTun + { + protected Socket _socket; + protected EndPoint _socketEndPoint; + protected IPEndPoint _remoteUDPEndPoint; + + protected bool _proxy; + protected string _proxy_server; + protected int _proxy_udp_port; + + protected const int RecvSize = 2048; + + private byte[] SendEncryptBuffer = new byte[RecvSize]; + private byte[] ReceiveDecryptBuffer = new byte[RecvSize * 2]; + + protected bool _close; + + public ProxySocketTun(AddressFamily af, SocketType type, ProtocolType protocol) + { + _socket = new Socket(af, type, protocol); + } + + public Socket GetSocket() + { + return _socket; + } + + public bool IsClose + { + get + { + return _close; + } + } + + public bool GoS5Proxy + { + get + { + return _proxy; + } + set + { + _proxy = value; + } + } + + public AddressFamily AddressFamily + { + get + { + return _socket.AddressFamily; + } + } + + public void Shutdown(SocketShutdown how) + { + _socket.Shutdown(how); + } + + public void Close() + { + _socket.Close(); + } + + public IAsyncResult BeginConnect(EndPoint ep, AsyncCallback callback, object state) + { + _close = false; + _socketEndPoint = ep; + return _socket.BeginConnect(ep, callback, state); + } + + public void EndConnect(IAsyncResult ar) + { + _socket.EndConnect(ar); + } + + public IAsyncResult BeginReceive(byte[] buffer, int size, SocketFlags flags, AsyncCallback callback, object state) + { + CallbackState st = new CallbackState(); + st.buffer = buffer; + st.size = size; + st.state = state; + return _socket.BeginReceive(buffer, 0, size, flags, callback, st); + } + + public int EndReceive(IAsyncResult ar, out bool sendback) + { + int bytesRead = _socket.EndReceive(ar); + sendback = false; + if (bytesRead > 0) + { + CallbackState st = (CallbackState)ar.AsyncState; + st.size = bytesRead; + return bytesRead; + } + else + { + _close = true; + } + return bytesRead; + } + + public int Send(byte[] buffer, int size, SocketFlags flags) + { + _socket.Send(buffer, size, 0); + return size; + } + + public int BeginSend(byte[] buffer, int size, SocketFlags flags, AsyncCallback callback, object state) + { + CallbackState st = new CallbackState(); + st.size = size; + st.state = state; + + _socket.BeginSend(buffer, 0, size, 0, callback, st); + return size; + } + + public int EndSend(IAsyncResult ar) + { + return _socket.EndSend(ar); + } + + public IAsyncResult BeginReceiveFrom(byte[] buffer, int size, SocketFlags flags, ref EndPoint ep, AsyncCallback callback, object state) + { + CallbackState st = new CallbackState(); + st.buffer = buffer; + st.size = size; + st.state = state; + return _socket.BeginReceiveFrom(buffer, 0, size, flags, ref ep, callback, st); + } + + public int GetAsyncResultSize(IAsyncResult ar) + { + CallbackState st = (CallbackState)ar.AsyncState; + return st.size; + } + + public byte[] GetAsyncResultBuffer(IAsyncResult ar) + { + CallbackState st = (CallbackState)ar.AsyncState; + return st.buffer; + } + + public bool ConnectSocks5ProxyServer(string strRemoteHost, int iRemotePort, bool udp, string socks5RemoteUsername, string socks5RemotePassword) + { + int socketErrorCode = (int)SocketError.ConnectionReset; + _proxy = true; + + //构造Socks5代理服务器第一连接头(无用户名密码) + byte[] bySock5Send = new Byte[10]; + bySock5Send[0] = 5; + bySock5Send[1] = 2; + bySock5Send[2] = 0; + bySock5Send[3] = 2; + + //发送Socks5代理第一次连接信息 + _socket.Send(bySock5Send, 4, SocketFlags.None); + + byte[] bySock5Receive = new byte[32]; + int iRecCount = _socket.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None); + + if (iRecCount < 2) + { + throw new SocketException(socketErrorCode); + //throw new Exception("不能获得代理服务器正确响应。"); + } + + if (bySock5Receive[0] != 5 || (bySock5Receive[1] != 0 && bySock5Receive[1] != 2)) + { + throw new SocketException(socketErrorCode); + //throw new Exception("代理服务其返回的响应错误。"); + } + + if (bySock5Receive[1] != 0) // auth + { + if (bySock5Receive[1] == 2) + { + if (socks5RemoteUsername.Length == 0) + { + throw new SocketException(socketErrorCode); + //throw new Exception("代理服务器需要进行身份确认。"); + } + else + { + bySock5Send = new Byte[socks5RemoteUsername.Length + socks5RemotePassword.Length + 3]; + bySock5Send[0] = 1; + bySock5Send[1] = (Byte)socks5RemoteUsername.Length; + for (int i = 0; i < socks5RemoteUsername.Length; ++i) + { + bySock5Send[2 + i] = (Byte)socks5RemoteUsername[i]; + } + bySock5Send[socks5RemoteUsername.Length + 2] = (Byte)socks5RemotePassword.Length; + for (int i = 0; i < socks5RemotePassword.Length; ++i) + { + bySock5Send[socks5RemoteUsername.Length + 3 + i] = (Byte)socks5RemotePassword[i]; + } + _socket.Send(bySock5Send, bySock5Send.Length, SocketFlags.None); + iRecCount = _socket.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None); + + if (bySock5Receive[0] != 1 || bySock5Receive[1] != 0) + { + throw new SocketException((int)SocketError.ConnectionRefused); + } + } + } + else + { + return false; + } + } + // connect + if (!udp) // TCP + { + List dataSock5Send = new List(); + dataSock5Send.Add(5); + dataSock5Send.Add(1); + dataSock5Send.Add(0); + + IPAddress ipAdd; + //bool ForceRemoteDnsResolve = false; + bool parsed = IPAddress.TryParse(strRemoteHost, out ipAdd); + //if (!parsed && !ForceRemoteDnsResolve) + //{ + // if (server.DnsTargetBuffer().isExpired(strRemoteHost)) + // { + // try + // { + // IPHostEntry ipHostInfo = Dns.GetHostEntry(strRemoteHost); + // ipAdd = ipHostInfo.AddressList[0]; + // server.DnsTargetBuffer().UpdateDns(strRemoteHost, ipAdd); + // } + // catch (Exception) + // { + // } + // } + // else + // { + // ipAdd = server.DnsTargetBuffer().ip; + // } + //} + if (ipAdd == null) + { + dataSock5Send.Add(3); // remote DNS resolve + dataSock5Send.Add((byte)strRemoteHost.Length); + for (int i = 0; i < strRemoteHost.Length; ++i) + { + dataSock5Send.Add((byte)strRemoteHost[i]); + } + } + else + { + byte[] addBytes = ipAdd.GetAddressBytes(); + if (addBytes.GetLength(0) > 4) + { + dataSock5Send.Add(4); // IPv6 + for (int i = 0; i < 16; ++i) + { + dataSock5Send.Add(addBytes[i]); + } + } + else + { + dataSock5Send.Add(1); // IPv4 + for (int i = 0; i < 4; ++i) + { + dataSock5Send.Add(addBytes[i]); + } + } + } + + dataSock5Send.Add((byte)(iRemotePort / 256)); + dataSock5Send.Add((byte)(iRemotePort % 256)); + + _socket.Send(dataSock5Send.ToArray(), dataSock5Send.Count, SocketFlags.None); + iRecCount = _socket.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None); + + if (iRecCount < 2 || bySock5Receive[0] != 5 || bySock5Receive[1] != 0) + { + throw new SocketException(socketErrorCode); + //throw new Exception("第二次连接Socks5代理返回数据出错。"); + } + return true; + } + else // UDP + { + List dataSock5Send = new List(); + dataSock5Send.Add(5); + dataSock5Send.Add(3); + dataSock5Send.Add(0); + + IPAddress ipAdd = ((IPEndPoint)_socketEndPoint).Address; + { + byte[] addBytes = ipAdd.GetAddressBytes(); + if (addBytes.GetLength(0) > 4) + { + dataSock5Send.Add(4); // IPv6 + for (int i = 0; i < 16; ++i) + { + dataSock5Send.Add(addBytes[i]); + } + } + else + { + dataSock5Send.Add(1); // IPv4 + for (int i = 0; i < 4; ++i) + { + dataSock5Send.Add(addBytes[i]); + } + } + } + + dataSock5Send.Add((byte)(0)); + dataSock5Send.Add((byte)(0)); + + _socket.Send(dataSock5Send.ToArray(), dataSock5Send.Count, SocketFlags.None); + iRecCount = _socket.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None); + + if (bySock5Receive[0] != 5 || bySock5Receive[1] != 0) + { + throw new SocketException(socketErrorCode); + //throw new Exception("第二次连接Socks5代理返回数据出错。"); + } + else + { + bool ipv6 = bySock5Receive[0] == 4; + byte[] addr; + int port; + if (!ipv6) + { + addr = new byte[4]; + Array.Copy(bySock5Receive, 4, addr, 0, 4); + port = bySock5Receive[8] * 0x100 + bySock5Receive[9]; + } + else + { + addr = new byte[16]; + Array.Copy(bySock5Receive, 4, addr, 0, 16); + port = bySock5Receive[20] * 0x100 + bySock5Receive[21]; + } + ipAdd = new IPAddress(addr); + _remoteUDPEndPoint = new IPEndPoint(ipAdd, port); + } + return true; + } + } + + public void SetTcpServer(string server, int port) + { + _proxy_server = server; + _proxy_udp_port = port; + } + + public void SetUdpServer(string server, int port) + { + _proxy_server = server; + _proxy_udp_port = port; + } + + public void SetUdpEndPoint(IPEndPoint ep) + { + _remoteUDPEndPoint = ep; + } + + public bool ConnectHttpProxyServer(string strRemoteHost, int iRemotePort, string socks5RemoteUsername, string socks5RemotePassword, string proxyUserAgent) + { + _proxy = true; + + IPAddress ipAdd; + //bool ForceRemoteDnsResolve = true; + bool parsed = IPAddress.TryParse(strRemoteHost, out ipAdd); + //if (!parsed && !ForceRemoteDnsResolve) + //{ + // if (server.DnsTargetBuffer().isExpired(strRemoteHost)) + // { + // try + // { + // IPHostEntry ipHostInfo = Dns.GetHostEntry(strRemoteHost); + // ipAdd = ipHostInfo.AddressList[0]; + // server.DnsTargetBuffer().UpdateDns(strRemoteHost, ipAdd); + // } + // catch (Exception) + // { + // } + // } + // else + // { + // ipAdd = server.DnsTargetBuffer().ip; + // } + //} + if (ipAdd != null) + { + strRemoteHost = ipAdd.ToString(); + } + string host = (strRemoteHost.IndexOf(':') >= 0 ? "[" + strRemoteHost + "]" : strRemoteHost) + ":" + iRemotePort.ToString(); + string authstr = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(socks5RemoteUsername + ":" + socks5RemotePassword)); + string cmd = "CONNECT " + host + " HTTP/1.0\r\n" + + "Host: " + host + "\r\n"; + if (proxyUserAgent != null && proxyUserAgent.Length > 0) + cmd += "User-Agent: " + proxyUserAgent + "\r\n"; + cmd += "Proxy-Connection: Keep-Alive\r\n"; + if (socks5RemoteUsername.Length > 0) + cmd += "Proxy-Authorization: Basic " + authstr + "\r\n"; + cmd += "\r\n"; + byte[] httpData = System.Text.Encoding.UTF8.GetBytes(cmd); + _socket.Send(httpData, httpData.Length, SocketFlags.None); + byte[] byReceive = new byte[1024]; + int iRecCount = _socket.Receive(byReceive, byReceive.Length, SocketFlags.None); + if (iRecCount > 13) + { + string data = System.Text.Encoding.UTF8.GetString(byReceive, 0, iRecCount); + string[] data_part = data.Split(' '); + if (data_part.Length > 1 && data_part[1] == "200") + { + return true; + } + } + return false; + } + } + + class ProxyEncryptSocket { protected Socket _socket; protected EndPoint _socketEndPoint; @@ -41,7 +463,7 @@ class ProxySocket protected bool _close; - public ProxySocket(AddressFamily af, SocketType type, ProtocolType protocol) + public ProxyEncryptSocket(AddressFamily af, SocketType type, ProtocolType protocol) { _socket = new Socket(af, type, protocol); } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index f8a67d9..e696cff 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading; using System.Net.Sockets; +using System.Net; namespace Shadowsocks.Controller { @@ -29,6 +30,7 @@ public class ShadowsocksController private PACServer _pacServer; private Configuration _config; private ServerTransferTotal _transfer; + public IPRangeSet _rangeSet; #if !_CONSOLE private HttpProxyRunner polipoRunner; #endif @@ -87,6 +89,16 @@ protected void ReportError(Exception e) } } + public void ReloadIPRange() + { + _rangeSet = new IPRangeSet(); + _rangeSet.LoadApnic("CN"); + if (_config.proxyRuleMode == 3) + { + _rangeSet.Reverse(); + } + } + public Server GetCurrentServer() { return _config.GetCurrentServer(); @@ -436,6 +448,7 @@ protected void Reload() // some logic in configuration updated the config when saving, we need to read it again _config = MergeGetConfiguration(_config); _config.FlushPortMapCache(); + ReloadIPRange(); #if !_CONSOLE if (polipoRunner == null) @@ -468,7 +481,7 @@ protected void Reload() { if (_listener != null && !_listener.isConfigChange(_config)) { - Local local = new Local(_config, _transfer); + Local local = new Local(_config, _transfer, _rangeSet); _listener.GetServices()[0] = local; #if !_CONSOLE if (polipoRunner.HasExited()) @@ -493,7 +506,7 @@ protected void Reload() polipoRunner.Start(_config); #endif - Local local = new Local(_config, _transfer); + Local local = new Local(_config, _transfer, _rangeSet); List services = new List(); services.Add(local); services.Add(_pacServer); @@ -541,7 +554,7 @@ protected void Reload() { try { - Local local = new Local(_config, _transfer); + Local local = new Local(_config, _transfer, _rangeSet); List services = new List(); services.Add(local); Listener listener = new Listener(services); diff --git a/shadowsocks-csharp/Controller/Socks5Forwarder.cs b/shadowsocks-csharp/Controller/Socks5Forwarder.cs index a6a048e..3f428d8 100644 --- a/shadowsocks-csharp/Controller/Socks5Forwarder.cs +++ b/shadowsocks-csharp/Controller/Socks5Forwarder.cs @@ -6,32 +6,42 @@ using System.Threading; using OpenDNS; using Shadowsocks.Model; +using Shadowsocks.Util; namespace Shadowsocks.Controller { class Socks5Forwarder : Listener.Service { - Configuration _config; + private Configuration _config; + private IPRangeSet _IPRange; - public Socks5Forwarder(Configuration config) + public Socks5Forwarder(Configuration config, IPRangeSet IPRange) { - this._config = config; + _config = config; + _IPRange = IPRange; } public bool Handle(byte[] firstPacket, int length, Socket socket) + { + int handle = IsHandle(firstPacket, length, socket); + if (handle > 0) + { + new Handler().Start(_config, _IPRange, firstPacket, length, socket, _config.proxyEnable && handle == 2); + return true; + } + return false; + } + + public int IsHandle(byte[] firstPacket, int length, Socket socket) { if (length >= 7) { + IPAddress ipAddress = null; if (firstPacket[0] == 1) { byte[] addr = new byte[4]; Array.Copy(firstPacket, 1, addr, 0, addr.Length); - IPAddress ipAddress = new IPAddress(addr); - if (_config.proxyRuleMode == 1 && Util.Utils.isLAN(ipAddress)) - { - new Handler().Start(_config, firstPacket, length, socket); - return true; - } + ipAddress = new IPAddress(addr); } else if (firstPacket[0] == 3) { @@ -41,21 +51,28 @@ public bool Handle(byte[] firstPacket, int length, Socket socket) { Array.Copy(firstPacket, 2, addr, 0, addr.Length); string host = Encoding.UTF8.GetString(firstPacket, 2, len); - IPAddress ipAddress; if (IPAddress.TryParse(host, out ipAddress)) { - if (_config.proxyRuleMode == 1 && Util.Utils.isLAN(ipAddress)) - { - new Handler().Start(_config, firstPacket, length, socket); - return true; - } + //pass } else { - if (_config.proxyRuleMode == 1 && host.ToLower() == "localhost") + if (_config.proxyRuleMode != 0 + && host.ToLower() == "localhost") //TODO: load system host file { - new Handler().Start(_config, firstPacket, length, socket); - return true; + return 1; + } + if (_config.proxyRuleMode == 2 && _IPRange != null) + { + ipAddress = Utils.DnsBuffer.Get(host); + if (ipAddress == null) + { + ipAddress = Util.Utils.QueryDns(host, _config.dns_server); + if (ipAddress != null) + { + Utils.DnsBuffer.Set(host, ipAddress); + } + } } } } @@ -64,155 +81,127 @@ public bool Handle(byte[] firstPacket, int length, Socket socket) { byte[] addr = new byte[16]; Array.Copy(firstPacket, 1, addr, 0, addr.Length); - IPAddress ipAddress = new IPAddress(addr); - if (_config.proxyRuleMode == 1 && Util.Utils.isLAN(ipAddress)) + ipAddress = new IPAddress(addr); + } + if (ipAddress != null) + { + if (_config.proxyRuleMode != 0 + && Util.Utils.isLAN(ipAddress)) + { + return 1; + } + if (_config.proxyRuleMode == 2 && _IPRange != null + && ipAddress.AddressFamily == AddressFamily.InterNetwork + ) { - new Handler().Start(_config, firstPacket, length, socket); - return true; + if (_IPRange.IsInIPRange(ipAddress)) + { + return 2; + } + Utils.DnsBuffer.Sweep(); } } } - return false; + return 0; } class Handler { - private delegate IPHostEntry GetHostEntryHandler(string ip); + private IPRangeSet _IPRange; + private Configuration _config; private byte[] _firstPacket; private int _firstPacketLength; private Socket _local; - private Socket _remote; + private ProxySocketTun _remote; + private bool _closed = false; - private Configuration _config; + private bool _remote_go_proxy = false; + private string _remote_host; + private int _remote_port; + public const int RecvSize = 4096; // remote receive buffer private byte[] remoteRecvBuffer = new byte[RecvSize]; // connection receive buffer private byte[] connetionRecvBuffer = new byte[RecvSize]; - public void Start(Configuration config, byte[] firstPacket, int length, Socket socket) + public void Start(Configuration config, IPRangeSet IPRange, byte[] firstPacket, int length, Socket socket, bool proxy) { + _IPRange = IPRange; _firstPacket = firstPacket; _firstPacketLength = length; _local = socket; _config = config; + _remote_go_proxy = proxy; Connect(); } - private void StartConnect() + private void Connect() { try { - Connect(); - } - catch (Exception e) - { - Logging.LogUsefulException(e); - Close(); - } - - } - - private IPAddress QueryDns(string host, string dns_servers) - { - IPAddress ipAddress; - bool parsed = IPAddress.TryParse(host, out ipAddress); - if (!parsed) - { - //if (server.DnsBuffer().isExpired(host)) + IPAddress ipAddress = null; + int _targetPort = 0; { - if (dns_servers != null && dns_servers.Length > 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(); + } + 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(); + } + else if (_firstPacket[0] == 3) { - OpenDNS.Types[] types; - //if (false) - // types = new Types[] { Types.AAAA, Types.A }; - //else - types = new Types[] { Types.A, Types.AAAA }; - string[] dns_server = dns_servers.Split(','); - for (int query_i = 0; query_i < types.Length; ++query_i) + 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); + + if (!_remote_go_proxy) { - DnsQuery dns = new DnsQuery(host, types[query_i]); - dns.RecursionDesired = true; - foreach (string server in dns_server) + if (!IPAddress.TryParse(_remote_host, out ipAddress)) { - dns.Servers.Add(server); + ipAddress = Utils.DnsBuffer.Get(_remote_host); } - if (dns.Send()) + if (ipAddress == null) { - int count = dns.Response.Answers.Count; - if (count > 0) - { - for (int i = 0; i < count; ++i) - { - if (((ResourceRecord)dns.Response.Answers[i]).Type != types[query_i]) - continue; - return ((OpenDNS.Address)dns.Response.Answers[i]).IP; - } - } + ipAddress = Utils.QueryDns(_remote_host, _config.dns_server); } - } - } - { - try - { - GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry); - IAsyncResult result = callback.BeginInvoke(host, null, null); - if (result.AsyncWaitHandle.WaitOne(5, false)) + if (ipAddress != null) { - foreach (IPAddress ad in callback.EndInvoke(result).AddressList) - { - return ad; - //if (ad.AddressFamily == AddressFamily.InterNetwork) - //{ - // return ad; - //} - } + Utils.DnsBuffer.Set(_remote_host, ipAddress); + Utils.DnsBuffer.Sweep(); + } + else + { + throw new SocketException((int)SocketError.HostNotFound); } } - catch - { - - } + _targetPort = (_firstPacket[len + 2] << 8) | _firstPacket[len + 3]; } + _remote_port = _targetPort; } - } - return ipAddress; - } - - private void Connect() - { - try - { - IPAddress ipAddress; - int _targetPort; - 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]; - } - 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]; - } - else //if (_firstPacket[0] == 3) + if (_remote_go_proxy) { - int len = _firstPacket[1]; - byte[] addr = new byte[len]; - Array.Copy(_firstPacket, 2, addr, 0, addr.Length); - ipAddress = QueryDns(Encoding.UTF8.GetString(_firstPacket, 2, len), _config.dns_server); - _targetPort = (_firstPacket[len + 2] << 8) | _firstPacket[len + 3]; + 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 Socket(ipAddress.AddressFamily, + _remote = new ProxySocketTun(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - _remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); + _remote.GetSocket().SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); // Connect to the remote endpoint. _remote.BeginConnect(remoteEP, @@ -225,6 +214,24 @@ private void Connect() } } + private bool ConnectProxyServer(string strRemoteHost, int iRemotePort) + { + if (_config.proxyType == 0) + { + bool ret = _remote.ConnectSocks5ProxyServer(strRemoteHost, iRemotePort, false, _config.proxyAuthUser, _config.proxyAuthPass); + return ret; + } + else if (_config.proxyType == 1) + { + bool ret = _remote.ConnectHttpProxyServer(strRemoteHost, iRemotePort, _config.proxyAuthUser, _config.proxyAuthPass, _config.proxyUserAgent); + return ret; + } + else + { + return true; + } + } + private void ConnectCallback(IAsyncResult ar) { if (_closed) @@ -234,6 +241,13 @@ private void ConnectCallback(IAsyncResult ar) try { _remote.EndConnect(ar); + if (_remote_go_proxy) + { + if (!ConnectProxyServer(_remote_host, _remote_port)) + { + throw new SocketException((int)SocketError.ConnectionReset); + } + } StartPipe(); } catch (Exception e) @@ -251,7 +265,7 @@ private void StartPipe() } try { - _remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, + _remote.BeginReceive(remoteRecvBuffer, RecvSize, 0, new AsyncCallback(PipeRemoteReceiveCallback), null); _local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeConnectionReceiveCallback), null); @@ -271,7 +285,8 @@ private void PipeRemoteReceiveCallback(IAsyncResult ar) } try { - int bytesRead = _remote.EndReceive(ar); + bool sendback; + int bytesRead = _remote.EndReceive(ar, out sendback); if (bytesRead > 0) { @@ -301,7 +316,7 @@ private void PipeConnectionReceiveCallback(IAsyncResult ar) if (bytesRead > 0) { - _remote.BeginSend(connetionRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeRemoteSendCallback), null); + _remote.BeginSend(connetionRecvBuffer, bytesRead, 0, new AsyncCallback(PipeRemoteSendCallback), null); } else { @@ -324,7 +339,7 @@ private void PipeRemoteSendCallback(IAsyncResult ar) try { _remote.EndSend(ar); - _local.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0, + _local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeConnectionReceiveCallback), null); } catch (Exception e) @@ -343,7 +358,7 @@ private void PipeConnectionSendCallback(IAsyncResult ar) try { _local.EndSend(ar); - _remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0, + _remote.BeginReceive(remoteRecvBuffer, RecvSize, 0, new AsyncCallback(PipeRemoteReceiveCallback), null); } catch (Exception e) @@ -364,26 +379,26 @@ public void Close() _closed = true; } Thread.Sleep(100); - if (_local != null) + if (_remote != null) { try { - _local.Shutdown(SocketShutdown.Both); - _local.Close(); + _remote.Shutdown(SocketShutdown.Both); + _remote.Close(); } - catch (Exception e) + catch (SocketException e) { Logging.LogUsefulException(e); } } - if (_remote != null) + if (_local != null) { try { - _remote.Shutdown(SocketShutdown.Both); - _remote.Close(); + _local.Shutdown(SocketShutdown.Both); + _local.Close(); } - catch (SocketException e) + catch (Exception e) { Logging.LogUsefulException(e); } diff --git a/shadowsocks-csharp/Controller/SystemProxy.cs b/shadowsocks-csharp/Controller/SystemProxy.cs index 979151d..88c2388 100755 --- a/shadowsocks-csharp/Controller/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/SystemProxy.cs @@ -77,7 +77,7 @@ public static void Update(Configuration config, bool forceDisable) else { string pacUrl; - pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now); + pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?" + "auth=" + config.localAuthPassword + "&t=" + GetTimestamp(DateTime.Now); RegistrySetValue(registry, "ProxyEnable", 0); RegistrySetValue(registry, "ProxyServer", ""); RegistrySetValue(registry, "AutoConfigURL", pacUrl); @@ -205,7 +205,7 @@ private static byte[] GenConnectionSettings(Configuration config, int sysProxyMo BytePushback(buffer, ref buffer_len, bypass); string pacUrl = ""; - pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now); + pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?" + "auth=" + config.localAuthPassword + "&t=" + GetTimestamp(DateTime.Now); BytePushback(buffer, ref buffer_len, pacUrl); buffer_len += 0x20; diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index 5cd1d61..6169838 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -21,7 +21,7 @@ public class UpdateChecker public const string Name = "ShadowsocksR"; public const string Copyright = "Copyright © BreakWall 2016. Fork from Shadowsocks by clowwindy"; - public const string Version = "3.9.5"; + public const string Version = "3.9.6"; public const string FullVersion = Version + ""; private static bool UseProxy = true; diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 108f444..75fc067 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -9,7 +9,9 @@ Mode=系统代理模式 PAC=PAC 模式 Global=全局模式 Proxy rule=代理规则 -Bypass Lan=绕过局域网 +Bypass LAN=绕过局域网 +Bypass LAN && China=绕过局域网和大陆 +Bypass LAN && not China=绕过局域网和非大陆 Disable bypass=全局 Servers=服务器 Edit servers...=编辑服务器... diff --git a/shadowsocks-csharp/Data/zh-tw.txt b/shadowsocks-csharp/Data/zh-tw.txt index d6e268e..d0f4b73 100644 --- a/shadowsocks-csharp/Data/zh-tw.txt +++ b/shadowsocks-csharp/Data/zh-tw.txt @@ -9,7 +9,9 @@ Mode=系統代理模式 PAC=PAC 模式 Global=全局模式 Proxy rule=代理規則 -Bypass Lan=绕过區域網路 +Bypass LAN=绕过區域網路 +Bypass LAN && China=绕过區域網路和大陸 +Bypass LAN && not China=绕过區域網路和非大陸 Disable bypass=全局 Servers=伺服器 Edit servers...=編輯伺服器... diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index 425bf91..3684759 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -292,10 +292,16 @@ public class Configuration public bool shareOverLan; public bool bypassWhiteList; public int localPort; + public string localAuthPassword; + + public string dns_server; public int reconnectTimes; public int randomAlgorithm; public int TTL; public int connect_timeout; + + public int proxyRuleMode; + public bool proxyEnable; public bool pacDirectGoProxy; public int proxyType; @@ -304,14 +310,17 @@ public class Configuration public string proxyAuthUser; public string proxyAuthPass; public string proxyUserAgent; + public string authUser; public string authPass; + public bool autoBan; public bool sameHostForSameTarget; + public int keepVisitTime; + public bool isHideTips; - public string dns_server; - public int proxyRuleMode; + public Dictionary token = new Dictionary(); public Dictionary portMap = new Dictionary(); @@ -522,28 +531,56 @@ public Configuration() portMap = new Dictionary(); } + public void FixConfiguration() + { + if (localPort == 0) + { + localPort = 1080; + } + if (keepVisitTime == 0) + { + keepVisitTime = 180; + } + if (portMap == null) + { + portMap = new Dictionary(); + } + if (token == null) + { + token = new Dictionary(); + } + if (connect_timeout == 0) + { + connect_timeout = 10; + reconnectTimes = 2; + TTL = 180; + keepVisitTime = 180; + } + if (localAuthPassword == null || localAuthPassword.Length < 16) + { + localAuthPassword = randString(20); + } + } + + private static string randString(int len) + { + string set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + string ret = ""; + Random random = new Random(); + for (int i = 0; i < len; ++i) + { + ret += set[random.Next(set.Length)]; + } + return ret; + } + public static Configuration LoadFile(string filename) { try { string configContent = File.ReadAllText(filename); Configuration config = SimpleJson.SimpleJson.DeserializeObject(configContent, new JsonSerializerStrategy()); - if (config.localPort == 0) - { - config.localPort = 1080; - } - if (config.keepVisitTime == 0) - { - config.keepVisitTime = 180; - } - if (config.portMap == null) - { - config.portMap = new Dictionary(); - } - if (config.token == null) - { - config.token = new Dictionary(); - } + config.FixConfiguration(); return config; } catch (Exception e) @@ -591,6 +628,7 @@ public Configuration Load(string config_str) try { Configuration config = SimpleJson.SimpleJson.DeserializeObject(config_str, new JsonSerializerStrategy()); + config.FixConfiguration(); return config; } catch diff --git a/shadowsocks-csharp/Model/IPRangeSet.cs b/shadowsocks-csharp/Model/IPRangeSet.cs new file mode 100644 index 0000000..bfa90ff --- /dev/null +++ b/shadowsocks-csharp/Model/IPRangeSet.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; + +namespace Shadowsocks.Model +{ + public class IPRangeSet + { + private const string APNIC_FILENAME = "delegated-apnic.txt"; + private uint[] _set; + + public IPRangeSet() + { + _set = new uint[256 * 256 * 8]; + } + + public void Insert(uint begin, uint size) + { + begin /= 256; + size /= 256; + for (uint i = begin; i < begin + size; ++i) + { + uint pos = i / 32; + int mv = (int)(i & 31); + _set[pos] |= (byte)(1u << mv); + } + } + + public bool isIn(uint ip) + { + ip /= 256; + uint pos = ip / 32; + int mv = (int)(ip & 31); + return (_set[pos] & (byte)(1u << mv)) != 0; + } + + public bool IsInIPRange(IPAddress addr) + { + byte[] bytes_addr = addr.GetAddressBytes(); + Array.Reverse(bytes_addr); + return isIn(BitConverter.ToUInt32(bytes_addr, 0)); + } + + public bool LoadApnic(string zone) + { + if (File.Exists(APNIC_FILENAME)) + { + try + { + using (StreamReader stream = File.OpenText(APNIC_FILENAME)) + { + while (true) + { + string line = stream.ReadLine(); + if (line == null) + break; + string[] parts = line.Split('|'); + if (parts.Length < 7) + continue; + if (parts[0] != "apnic" || parts[1] != zone || parts[2] != "ipv4") + continue; + IPAddress addr; + IPAddress.TryParse(parts[3], out addr); + byte[] bytes_addr = addr.GetAddressBytes(); + Array.Reverse(bytes_addr); + uint start = BitConverter.ToUInt32(bytes_addr, 0); + uint size = UInt32.Parse(parts[4]); + Insert(start, size); + } + } + return true; + } + catch + { + return false; + } + } + return false; + } + + public void Reverse() + { + for (uint i = 0; i < _set.Length; ++i) + { + _set[i] = ~_set[i]; + } + } + } +} diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index b587416..d1a6c95 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -23,15 +23,116 @@ public bool isExpired(string host) { if (updateTime == null) return true; if (this.host != host) return true; - return (DateTime.Now - updateTime).TotalMinutes > 10; + return (DateTime.Now - updateTime).TotalMinutes > 30; } public void UpdateDns(string host, IPAddress ip) { updateTime = DateTime.Now; this.ip = new IPAddress(ip.GetAddressBytes()); - this.host = (string)host.Clone(); + this.host = host; } } + + public class LRUCache + { + protected Dictionary _store = new Dictionary(); + protected Dictionary _key_2_time = new Dictionary(); + protected Dictionary _time_2_key = new Dictionary(); + protected object _lock = new object(); + protected int _sweep_time; + + public LRUCache(int sweep_time = 60 * 60) + { + _sweep_time = sweep_time; + } + + public V Get(K key) + { + lock (_lock) + { + if (_store.ContainsKey(key)) + { + DateTime t = _key_2_time[key]; + _key_2_time.Remove(key); + _time_2_key.Remove(t); + t = DateTime.Now; + while (_time_2_key.ContainsKey(t)) + { + t = t.AddTicks(1); + } + _time_2_key[t] = key; + _key_2_time[key] = t; + return _store[key]; + } + return default(V); + } + } + + public V Set(K key, V val) + { + lock (_lock) + { + DateTime t; + if (_store.ContainsKey(key)) + { + t = _key_2_time[key]; + _key_2_time.Remove(key); + _time_2_key.Remove(t); + } + t = DateTime.Now; + while (_time_2_key.ContainsKey(t)) + { + t = t.AddTicks(1); + } + _time_2_key[t] = key; + _key_2_time[key] = t; + _store[key] = val; + return val; + } + } + + public void Del(K key) + { + lock (_lock) + { + DateTime t; + if (_store.ContainsKey(key)) + { + t = _key_2_time[key]; + _key_2_time.Remove(key); + _time_2_key.Remove(t); + _store.Remove(key); + } + } + } + + public void Sweep() + { + lock (_lock) + { + DateTime now = DateTime.Now; + for (int i = 0; i < 10; ++i) + { + bool finish = false; + foreach (KeyValuePair p in _time_2_key) + { + if ((now - p.Key).TotalSeconds < _sweep_time) + { + finish = true; + break; + } + _key_2_time.Remove(p.Value); + _time_2_key.Remove(p.Key); + _store.Remove(p.Value); + break; + } + if (finish) + break; + } + } + } + } + public class Connections { private System.Collections.Generic.Dictionary sockets = new Dictionary(); diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index f13da00..44065f0 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -10,11 +10,25 @@ using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; +using OpenDNS; +using Shadowsocks.Model; namespace Shadowsocks.Util { public class Utils { + private delegate IPHostEntry GetHostEntryHandler(string ip); + + private static LRUCache dnsBuffer = new LRUCache(); + + public static LRUCache DnsBuffer + { + get + { + return dnsBuffer; + } + } + public static void ReleaseMemory() { #if !_CONSOLE @@ -252,6 +266,67 @@ public static void SetArrayMinSize2(ref T[] array, int size) } } + public static IPAddress QueryDns(string host, string dns_servers, bool IPv6_first = false) + { + IPAddress ipAddress = null; + { + if (dns_servers != null && dns_servers.Length > 0) + { + OpenDNS.Types[] types; + if (IPv6_first) + types = new Types[] { Types.AAAA, Types.A }; + else + types = new Types[] { Types.A, Types.AAAA }; + string[] dns_server = dns_servers.Split(','); + for (int query_i = 0; query_i < types.Length; ++query_i) + { + DnsQuery dns = new DnsQuery(host, types[query_i]); + dns.RecursionDesired = true; + foreach (string server in dns_server) + { + dns.Servers.Add(server); + } + if (dns.Send()) + { + int count = dns.Response.Answers.Count; + if (count > 0) + { + for (int i = 0; i < count; ++i) + { + if (((ResourceRecord)dns.Response.Answers[i]).Type != types[query_i]) + continue; + return ((OpenDNS.Address)dns.Response.Answers[i]).IP; + } + } + } + } + } + { + try + { + GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry); + IAsyncResult result = callback.BeginInvoke(host, null, null); + if (result.AsyncWaitHandle.WaitOne(5, false)) + { + foreach (IPAddress ad in callback.EndInvoke(result).AddressList) + { + return ad; + //if (ad.AddressFamily == AddressFamily.InterNetwork) + //{ + // return ad; + //} + } + } + } + catch + { + + } + } + } + return ipAddress; + } + public static int GetDpiMul() { int dpi; diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 3dd88ef..36233fe 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -722,7 +722,8 @@ private void InitializeComponent() // // ConfigForm // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.BackColor = System.Drawing.SystemColors.Control; diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 4b5e4f1..e2b2652 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -63,16 +63,16 @@ public ConfigForm(ShadowsocksController controller, UpdateChecker updateChecker, PictureQRcode.Visible = false; int dpi_mul = Util.Utils.GetDpiMul(); - ServersListBox.Width = ServersListBox.Width * dpi_mul / 4; - ServersListBox.Height = ServersListBox.Height * dpi_mul / 4; - AddButton.Width = AddButton.Width * dpi_mul / 4; - AddButton.Height = AddButton.Height * dpi_mul / 4; - DeleteButton.Width = DeleteButton.Width * dpi_mul / 4; - DeleteButton.Height = DeleteButton.Height * dpi_mul / 4; - UpButton.Width = UpButton.Width * dpi_mul / 4; - UpButton.Height = UpButton.Height * dpi_mul / 4; - DownButton.Width = DownButton.Width * dpi_mul / 4; - DownButton.Height = DownButton.Height * dpi_mul / 4; + //ServersListBox.Width = ServersListBox.Width * dpi_mul / 4; + //ServersListBox.Height = ServersListBox.Height * dpi_mul / 4; + //AddButton.Width = AddButton.Width * dpi_mul / 4; + //AddButton.Height = AddButton.Height * dpi_mul / 4; + //DeleteButton.Width = DeleteButton.Width * dpi_mul / 4; + //DeleteButton.Height = DeleteButton.Height * dpi_mul / 4; + //UpButton.Width = UpButton.Width * dpi_mul / 4; + //UpButton.Height = UpButton.Height * dpi_mul / 4; + //DownButton.Width = DownButton.Width * dpi_mul / 4; + //DownButton.Height = DownButton.Height * dpi_mul / 4; //IPTextBox.Width = IPTextBox.Width * dpi_mul / 4; //ServerPortTextBox.Width = ServerPortTextBox.Width * dpi_mul / 4; @@ -109,7 +109,7 @@ public ConfigForm(ShadowsocksController controller, UpdateChecker updateChecker, //OKButton.Width = OKButton.Width * dpi_mul / 4; ////OKButton.Height = OKButton.Height * dpi_mul / 4; - DrawLogo(350 * dpi_mul / 4); + DrawLogo(350 * 4 / 4); ShowWindow(); diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 5c3cd8d..9470271 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -33,8 +33,12 @@ public class MenuViewController private MenuItem PACModeItem; private MenuItem globalModeItem; private MenuItem modeItem; + private MenuItem ruleBypassLan; + private MenuItem ruleBypassChina; + private MenuItem ruleBypassNotChina; private MenuItem ruleDisableBypass; + private MenuItem SeperatorItem; private MenuItem ServersItem; private MenuItem SelectRandomItem; @@ -205,7 +209,10 @@ private void LoadMenu() CreateMenuItem("Edit user rule for GFWList...", new EventHandler(this.EditUserRuleFileForGFWListItem_Click)), }), CreateMenuGroup("Proxy rule", new MenuItem[] { - ruleBypassLan = CreateMenuItem("Bypass Lan", new EventHandler(this.RuleBypassLanItem_Click)), + ruleBypassLan = CreateMenuItem("Bypass LAN", new EventHandler(this.RuleBypassLanItem_Click)), + ruleBypassChina = CreateMenuItem("Bypass LAN && China", new EventHandler(this.RuleBypassChinaItem_Click)), + ruleBypassNotChina = CreateMenuItem("Bypass LAN && not China", new EventHandler(this.RuleBypassNotChinaItem_Click)), + new MenuItem("-"), ruleDisableBypass = CreateMenuItem("Disable bypass", new EventHandler(this.RuleBypassDisableItem_Click)), }), new MenuItem("-"), @@ -343,6 +350,8 @@ private void UpdateProxyRule(Configuration config) { ruleDisableBypass.Checked = config.proxyRuleMode == 0; ruleBypassLan.Checked = config.proxyRuleMode == 1; + ruleBypassChina.Checked = config.proxyRuleMode == 2; + ruleBypassNotChina.Checked = config.proxyRuleMode == 3; } private void LoadCurrentConfiguration() @@ -637,6 +646,16 @@ private void RuleBypassLanItem_Click(object sender, EventArgs e) controller.ToggleRuleMode(1); } + private void RuleBypassChinaItem_Click(object sender, EventArgs e) + { + controller.ToggleRuleMode(2); + } + + private void RuleBypassNotChinaItem_Click(object sender, EventArgs e) + { + controller.ToggleRuleMode(3); + } + private void RuleBypassDisableItem_Click(object sender, EventArgs e) { controller.ToggleRuleMode(0); @@ -768,14 +787,6 @@ private void CopyAddress_Click(object sender, EventArgs e) } } - private void QRCodeItem_Click(object sender, EventArgs e) - { - QRCodeForm qrCodeForm = new QRCodeForm(controller.GetSSLinkForCurrentServer()); - //qrCodeForm.Icon = this.Icon; - // TODO - qrCodeForm.Show(); - } - private bool ScanQRCode(Screen screen, Bitmap fullImage, Rectangle cropRect, out string url, out Rectangle rect) { Bitmap target = new Bitmap(cropRect.Width, cropRect.Height); diff --git a/shadowsocks-csharp/View/QRCodeForm.Designer.cs b/shadowsocks-csharp/View/QRCodeForm.Designer.cs deleted file mode 100755 index 0df7052..0000000 --- a/shadowsocks-csharp/View/QRCodeForm.Designer.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace Shadowsocks.View -{ - partial class QRCodeForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.pictureBox1 = new System.Windows.Forms.PictureBox(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); - this.SuspendLayout(); - // - // pictureBox1 - // - this.pictureBox1.Location = new System.Drawing.Point(10, 10); - this.pictureBox1.Margin = new System.Windows.Forms.Padding(0); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(210, 210); - this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; - this.pictureBox1.TabIndex = 1; - this.pictureBox1.TabStop = false; - // - // QRCodeForm - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.BackColor = System.Drawing.Color.White; - this.ClientSize = new System.Drawing.Size(338, 274); - this.Controls.Add(this.pictureBox1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "QRCodeForm"; - this.Padding = new System.Windows.Forms.Padding(10); - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "QRCode"; - this.Load += new System.EventHandler(this.QRCodeForm_Load); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.PictureBox pictureBox1; - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs deleted file mode 100755 index 2741d4f..0000000 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ /dev/null @@ -1,60 +0,0 @@ -using ZXing.QrCode.Internal; -using Shadowsocks.Controller; -using Shadowsocks.Properties; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.IO; -using System.IO.Compression; -using System.Text; -using System.Windows.Forms; - -namespace Shadowsocks.View -{ - public partial class QRCodeForm : Form - { - private string code; - - public QRCodeForm(string code) - { - this.code = code; - InitializeComponent(); - this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); - this.Text = I18N.GetString("QRCode"); - } - - private void GenQR(string ssconfig) - { - string qrText = ssconfig; - QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M); - ByteMatrix m = code.Matrix; - int blockSize = Math.Max(pictureBox1.Height / m.Height, 1); - Bitmap drawArea = new Bitmap((m.Width * blockSize), (m.Height * blockSize)); - using (Graphics g = Graphics.FromImage(drawArea)) - { - g.Clear(Color.White); - using (Brush b = new SolidBrush(Color.Black)) - { - for (int row = 0; row < m.Width; row++) - { - for (int col = 0; col < m.Height; col++) - { - if (m[row, col] != 0) - { - g.FillRectangle(b, blockSize * row, blockSize * col, blockSize, blockSize); - } - } - } - } - } - pictureBox1.Image = drawArea; - } - - private void QRCodeForm_Load(object sender, EventArgs e) - { - GenQR(code); - } - } -} diff --git a/shadowsocks-csharp/View/QRCodeForm.resx b/shadowsocks-csharp/View/QRCodeForm.resx deleted file mode 100755 index 5ea0895..0000000 --- a/shadowsocks-csharp/View/QRCodeForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/shadowsocks-csharp/View/SettingsForm.Designer.cs b/shadowsocks-csharp/View/SettingsForm.Designer.cs index c2ce43f..f617fdc 100644 --- a/shadowsocks-csharp/View/SettingsForm.Designer.cs +++ b/shadowsocks-csharp/View/SettingsForm.Designer.cs @@ -68,11 +68,11 @@ private void InitializeComponent() this.ReconnectText = new System.Windows.Forms.TextBox(); this.TTLLabel = new System.Windows.Forms.Label(); this.TTLText = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.DNSText = new System.Windows.Forms.TextBox(); this.labelTimeout = new System.Windows.Forms.Label(); this.textTimeout = new System.Windows.Forms.TextBox(); + this.DNSText = new System.Windows.Forms.TextBox(); this.buttonDefault = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); this.tableLayoutPanel1.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); this.Socks5ProxyGroup.SuspendLayout(); @@ -586,26 +586,6 @@ private void InitializeComponent() this.TTLText.TabIndex = 4; this.TTLText.WordWrap = false; // - // label2 - // - this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(40, 38); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(34, 17); - this.label2.TabIndex = 3; - this.label2.Text = "DNS"; - // - // DNSText - // - this.DNSText.ImeMode = System.Windows.Forms.ImeMode.Off; - this.DNSText.Location = new System.Drawing.Point(80, 35); - this.DNSText.MaxLength = 0; - this.DNSText.Name = "DNSText"; - this.DNSText.Size = new System.Drawing.Size(109, 23); - this.DNSText.TabIndex = 4; - this.DNSText.WordWrap = false; - // // labelTimeout // this.labelTimeout.Anchor = System.Windows.Forms.AnchorStyles.Right; @@ -626,6 +606,16 @@ private void InitializeComponent() this.textTimeout.TabIndex = 4; this.textTimeout.WordWrap = false; // + // DNSText + // + this.DNSText.ImeMode = System.Windows.Forms.ImeMode.Off; + this.DNSText.Location = new System.Drawing.Point(80, 35); + this.DNSText.MaxLength = 0; + this.DNSText.Name = "DNSText"; + this.DNSText.Size = new System.Drawing.Size(109, 23); + this.DNSText.TabIndex = 4; + this.DNSText.WordWrap = false; + // // buttonDefault // this.buttonDefault.Location = new System.Drawing.Point(80, 6); @@ -636,9 +626,20 @@ private void InitializeComponent() this.buttonDefault.UseVisualStyleBackColor = true; this.buttonDefault.Click += new System.EventHandler(this.buttonDefault_Click); // + // label2 + // + this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(40, 38); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(34, 17); + this.label2.TabIndex = 3; + this.label2.Text = "DNS"; + // // SettingsForm // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.ClientSize = new System.Drawing.Size(728, 573); diff --git a/shadowsocks-csharp/View/ShowTextForm.Designer.cs b/shadowsocks-csharp/View/ShowTextForm.Designer.cs index da95705..25ae6df 100644 --- a/shadowsocks-csharp/View/ShowTextForm.Designer.cs +++ b/shadowsocks-csharp/View/ShowTextForm.Designer.cs @@ -55,7 +55,8 @@ private void InitializeComponent() // // ShowTextForm // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(350, 418); this.Controls.Add(this.PictureQRcode); this.Controls.Add(this.textBox); diff --git a/shadowsocks-csharp/View/ShowTextForm.cs b/shadowsocks-csharp/View/ShowTextForm.cs index 4d084e6..3ca6be4 100644 --- a/shadowsocks-csharp/View/ShowTextForm.cs +++ b/shadowsocks-csharp/View/ShowTextForm.cs @@ -18,13 +18,14 @@ public ShowTextForm(string title, string text) InitializeComponent(); this.Text = title; + PictureQRcode.Height = this.ClientSize.Height - textBox.Height; textBox.Text = text; } private void GenQR(string ssconfig) { int dpi_mul = Util.Utils.GetDpiMul(); - int width = Math.Min(PictureQRcode.Width, PictureQRcode.Height) * dpi_mul / 4; + int width = Math.Min(PictureQRcode.Width, PictureQRcode.Height) * 4 / 4; { string qrText = ssconfig; QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M); diff --git a/shadowsocks-csharp/shadowsocks-csharp-console.csproj b/shadowsocks-csharp/shadowsocks-csharp-console.csproj index 17e31ae..b022e10 100644 --- a/shadowsocks-csharp/shadowsocks-csharp-console.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp-console.csproj @@ -103,6 +103,7 @@ + diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 3932e25..5c4ae37 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -158,6 +158,7 @@ + @@ -188,12 +189,6 @@ - - Form - - - QRCodeForm.cs - Form @@ -224,9 +219,6 @@ Designer Resources.Designer.cs - - QRCodeForm.cs - ServerLogForm.cs diff --git a/shadowsocks-csharp/shadowsocks-csharp4.0.csproj b/shadowsocks-csharp/shadowsocks-csharp4.0.csproj index 08435d9..5da7bdd 100644 --- a/shadowsocks-csharp/shadowsocks-csharp4.0.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp4.0.csproj @@ -157,6 +157,7 @@ + @@ -186,12 +187,6 @@ - - Form - - - QRCodeForm.cs - Form @@ -222,9 +217,6 @@ Designer Resources.Designer.cs - - QRCodeForm.cs - ServerLogForm.cs