diff --git a/.gitignore b/.gitignore index 940794e..1e2ef04 100644 --- a/.gitignore +++ b/.gitignore @@ -286,3 +286,9 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs + +# macOS auto-generated file +.DS_Store + +# VS Code files +.vscode/ diff --git a/DotfuscatorAttribute.cs b/DotfuscatorAttribute.cs new file mode 100644 index 0000000..cc0f60f --- /dev/null +++ b/DotfuscatorAttribute.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; + +[AttributeUsage(AttributeTargets.Assembly), ComVisible(false)] +public sealed class DotfuscatorAttribute : Attribute +{ + private string a; + + private int c; + + public string A + { + get + { + return this.a; + } + } + + public int C + { + get + { + return this.c; + } + } + + public DotfuscatorAttribute(string a, int c) + { + this.a = a; + this.c = c; + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d1cd3bc --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,21 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: Dotfuscator("000:0:0:5.5.4521.29298", 0)] +[assembly: AssemblyCompany("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyProduct("socks5")] +[assembly: AssemblyTitle("socks5")] +[assembly: AssemblyTrademark("")] +[assembly: CompilationRelaxations(8)] +[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: ComVisible(false)] +[assembly: Guid("9a9d914e-8de4-4f84-b38e-67ed719319fa")] +[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")] diff --git a/README.md b/README.md index ac9e6d0..4b6471e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # ssr868 -Decompiled code (by ILSpy) of breakwa11's passive Shadowsocks detector. + +Decompiled code (by ILSpy) of [breakwa11's passive Shadowsocks detector](https://github.com/breakwa11/shadowsocks-rss/issues/868). + +The code is generated by [ILSpy 2.4](http://ilspy.net/). I haven't yet tried to compile it, so it is just for reference. diff --git a/a.cs b/a.cs new file mode 100644 index 0000000..3c03149 --- /dev/null +++ b/a.cs @@ -0,0 +1,344 @@ +using socks5.Model; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Cryptography; + +internal class a +{ + private delegate IPHostEntry b(string A_0); + + public enum a + { + a = 117, + b + } + + private static LRUCache a = new LRUCache(3600); + + private static Process b = Process.GetCurrentProcess(); + + public static LRUCache d() + { + return global::a.a; + } + + public static void c() + { + GC.Collect(GC.MaxGeneration); + GC.WaitForPendingFinalizers(); + if (UIntPtr.Size == 4) + { + global::a.SetProcessWorkingSetSize(global::a.b.Handle, (UIntPtr)4294967295u, (UIntPtr)4294967295u); + return; + } + if (UIntPtr.Size == 8) + { + global::a.SetProcessWorkingSetSize(global::a.b.Handle, (UIntPtr)18446744073709551615uL, (UIntPtr)18446744073709551615uL); + } + } + + public static void a(byte[] A_0, int A_1) + { + byte[] array = new byte[A_1]; + new RNGCryptoServiceProvider().GetBytes(array); + array.CopyTo(A_0, 0); + } + + public static uint b() + { + byte[] array = new byte[4]; + new RNGCryptoServiceProvider().GetBytes(array); + return BitConverter.ToUInt32(array, 0); + } + + public static void a(IList A_0, Random A_1) + { + int i = A_0.Count; + while (i > 1) + { + int index = A_1.Next(i); + i--; + a value = A_0[index]; + A_0[index] = A_0[i]; + A_0[i] = value; + } + } + + public static bool a(byte[] A_0, int A_1, byte[] A_2, int A_3, int A_4) + { + for (int i = 0; i < A_4; i++) + { + if (A_0[A_1 + i] != A_2[A_3 + i]) + { + return false; + } + } + return true; + } + + public static int a(byte[] A_0, int A_1, byte[] A_2) + { + if (A_2.Length != 0 && A_1 >= A_2.Length) + { + for (int i = 0; i <= A_1 - A_2.Length; i++) + { + if (A_0[i] == A_2[0]) + { + int num = 1; + while (num < A_2.Length && A_0[i + num] == A_2[num]) + { + num++; + } + if (num >= A_2.Length) + { + return i; + } + } + } + } + return -1; + } + + public static bool a(IPAddress A_0, IPAddress A_1, int A_2) + { + byte[] addressBytes = A_0.GetAddressBytes(); + byte[] addressBytes2 = A_1.GetAddressBytes(); + int i = 8; + int num = 0; + while (i < A_2) + { + if (addressBytes[num] != addressBytes2[num]) + { + return false; + } + i += 8; + num++; + } + return addressBytes[num] >> i - A_2 == addressBytes2[num] >> i - A_2; + } + + public static bool a(IPAddress A_0, string A_1) + { + string[] array = A_1.Split(new char[] + { + '/' + }); + IPAddress iPAddress = IPAddress.Parse(array[0]); + if (A_0.AddressFamily == iPAddress.AddressFamily) + { + try + { + bool result = global::a.a(A_0, iPAddress, (int)Convert.ToInt16(array[1])); + return result; + } + catch + { + bool result = false; + return result; + } + return false; + } + return false; + } + + public static bool b(IPAddress A_0) + { + byte[] addressBytes = A_0.GetAddressBytes(); + if (addressBytes.Length == 4) + { + string[] array = new string[] + { + "127.0.0.0/8", + "169.254.0.0/16" + }; + for (int i = 0; i < array.Length; i++) + { + string a_ = array[i]; + if (global::a.a(A_0, a_)) + { + return true; + } + } + return false; + } + if (addressBytes.Length == 16) + { + string[] array = new string[] + { + "::1/128" + }; + for (int i = 0; i < array.Length; i++) + { + string a_2 = array[i]; + if (global::a.a(A_0, a_2)) + { + return true; + } + } + return false; + } + return true; + } + + public static bool b(Socket A_0) + { + return global::a.b(((IPEndPoint)A_0.RemoteEndPoint).Address); + } + + public static bool a(IPAddress A_0) + { + byte[] addressBytes = A_0.GetAddressBytes(); + if (addressBytes.Length == 4) + { + if (A_0.Equals(new IPAddress(0L))) + { + return false; + } + string[] array = new string[] + { + "0.0.0.0/8", + "10.0.0.0/8", + "127.0.0.0/8", + "169.254.0.0/16", + "172.16.0.0/12", + "192.168.0.0/16" + }; + for (int i = 0; i < array.Length; i++) + { + string a_ = array[i]; + if (global::a.a(A_0, a_)) + { + return true; + } + } + return false; + } + else + { + if (addressBytes.Length == 16) + { + string[] array = new string[] + { + "::1/128", + "fc00::/7", + "fe80::/10" + }; + for (int i = 0; i < array.Length; i++) + { + string a_2 = array[i]; + if (global::a.a(A_0, a_2)) + { + return true; + } + } + return false; + } + return true; + } + } + + public static bool a(Socket A_0) + { + return global::a.a(((IPEndPoint)A_0.RemoteEndPoint).Address); + } + + public static string a(DateTime A_0) + { + return A_0.ToString("yyyyMMddHHmmssffff"); + } + + public static string a(string A_0) + { + string text = ""; + for (int i = 0; i < A_0.Length; i++) + { + if (A_0[i] == '%' && i < A_0.Length - 2) + { + string arg_34_0 = A_0.Substring(i + 1, 2).ToLower(); + int num = 0; + char c = arg_34_0[0]; + char c2 = arg_34_0[1]; + num += (int)((c < 'a') ? (c - '0') : ('\n' + (c - 'a'))); + num *= 16; + num += (int)((c2 < 'a') ? (c2 - '0') : ('\n' + (c2 - 'a'))); + text += ((char)num).ToString(); + i += 2; + } + else if (A_0[i] == '+') + { + text += " "; + } + else + { + text += A_0[i].ToString(); + } + } + return text; + } + + public static void b(ref a[] A_0, int A_1) + { + if (A_1 > A_0.Length) + { + Array.Resize(ref A_0, A_1); + } + } + + public static void a(ref a[] A_0, int A_1) + { + if (A_1 > A_0.Length) + { + Array.Resize(ref A_0, A_1 * 2); + } + } + + public static IPAddress a(string A_0, string A_1, bool A_2 = false) + { + IPAddress result = null; + try + { + global::a.b b = new global::a.b(Dns.GetHostEntry); + IAsyncResult asyncResult = b.BeginInvoke(A_0, null, null); + if (asyncResult.AsyncWaitHandle.WaitOne(10000, true)) + { + IPHostEntry iPHostEntry = b.EndInvoke(asyncResult); + IPAddress[] addressList = iPHostEntry.AddressList; + int i; + for (i = 0; i < addressList.Length; i++) + { + IPAddress iPAddress = addressList[i]; + if (iPAddress.AddressFamily == AddressFamily.InterNetwork) + { + IPAddress result2 = iPAddress; + return result2; + } + } + addressList = iPHostEntry.AddressList; + i = 0; + if (i < addressList.Length) + { + IPAddress result2 = addressList[i]; + return result2; + } + } + } + catch + { + } + return result; + } + + public static string a() + { + return Assembly.GetExecutingAssembly().Location; + } + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool SetProcessWorkingSetSize(IntPtr A_0, UIntPtr A_1, UIntPtr A_2); +} diff --git a/b.cs b/b.cs new file mode 100644 index 0000000..696866c --- /dev/null +++ b/b.cs @@ -0,0 +1,433 @@ +using socks5.Controller; +using socks5.Model; +using System; +using System.Net; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Timers; + +internal class b +{ + private class a : IHandler + { + private Configuration a; + + private byte[] b; + + private int c; + + private ProxySocketTunLocal d; + + private ProxySocketTun e; + + private bool f; + + private bool g; + + private string h; + + private int i; + + public const int j = 11680; + + private byte[] k = new byte[11680]; + + private byte[] l = new byte[11680]; + + private int m; + + protected int n = 600; + + protected System.Timers.Timer o; + + protected object p = new object(); + + protected DateTime q; + + public void a(Configuration A_0, byte[] A_1, int A_2, Socket A_3, string A_4, bool A_5) + { + this.b = A_1; + this.c = A_2; + this.d = new ProxySocketTunLocal(A_3); + this.d.local_sendback_protocol = A_4; + this.a = A_0; + this.g = A_5; + this.d(); + } + + private void d() + { + try + { + IPAddress iPAddress = null; + int port = 0; + if (this.b[0] == 1) + { + byte[] array = new byte[4]; + Array.Copy(this.b, 1, array, 0, array.Length); + iPAddress = new IPAddress(array); + port = ((int)this.b[5] << 8 | (int)this.b[6]); + this.h = iPAddress.ToString(); + } + else if (this.b[0] == 4) + { + byte[] array2 = new byte[16]; + Array.Copy(this.b, 1, array2, 0, array2.Length); + iPAddress = new IPAddress(array2); + port = ((int)this.b[17] << 8 | (int)this.b[18]); + this.h = iPAddress.ToString(); + } + else if (this.b[0] == 3) + { + int num = (int)this.b[1]; + byte[] array3 = new byte[num]; + Array.Copy(this.b, 2, array3, 0, array3.Length); + this.h = Encoding.UTF8.GetString(this.b, 2, num); + port = ((int)this.b[num + 2] << 8 | (int)this.b[num + 3]); + if (!IPAddress.TryParse(this.h, out iPAddress) && iPAddress == null) + { + iPAddress = global::a.d().Get(this.h); + } + if (iPAddress == null) + { + iPAddress = global::a.a(this.h, null, false); + } + if (iPAddress != null) + { + global::a.d().Set(this.h, new IPAddress(iPAddress.GetAddressBytes())); + global::a.d().Sweep(); + } + else if (!this.g) + { + throw new SocketException(11001); + } + } + this.i = port; + IPEndPoint ep = new IPEndPoint(iPAddress, port); + this.e = new ProxySocketTun(iPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + this.e.GetSocket().NoDelay = true; + this.e.BeginConnect(ep, new AsyncCallback(this.c), null); + } + catch (Exception arg_1D1_0) + { + Logging.LogUsefulException(arg_1D1_0); + this.e(); + } + } + + private bool a(string A_0, int A_1) + { + return true; + } + + private void c(IAsyncResult A_0) + { + if (this.f) + { + return; + } + try + { + this.e.EndConnect(A_0); + if (this.g && !this.a(this.h, this.i)) + { + throw new SocketException(10054); + } + this.c(); + } + catch (Exception arg_45_0) + { + Logging.LogUsefulException(arg_45_0); + this.e(); + } + } + + private void a(double A_0) + { + if (A_0 <= 0.0 && this.o == null) + { + return; + } + if (A_0 <= 0.0) + { + if (this.o == null) + { + return; + } + object obj = this.p; + lock (obj) + { + if (this.o != null) + { + this.o.Enabled = false; + this.o.Elapsed -= new ElapsedEventHandler(this.a); + this.o.Dispose(); + this.o = null; + } + return; + } + } + DateTime arg_8F_0 = this.q; + if ((DateTime.Now - this.q).TotalMilliseconds > 500.0) + { + object obj = this.p; + lock (obj) + { + if (this.o == null) + { + this.o = new System.Timers.Timer(A_0 * 1000.0); + this.o.Elapsed += new ElapsedEventHandler(this.a); + } + else + { + this.o.Interval = A_0 * 1000.0; + this.o.Stop(); + } + this.o.Start(); + this.q = DateTime.Now; + } + } + } + + private void a(object A_0, ElapsedEventArgs A_1) + { + if (this.f) + { + return; + } + this.e(); + } + + private void c() + { + if (this.f) + { + return; + } + try + { + this.e.BeginReceive(this.k, 11680, SocketFlags.None, new AsyncCallback(this.b), null); + this.d.BeginReceive(this.l, 11680, SocketFlags.None, new AsyncCallback(this.a), null); + this.d.Send(this.l, 0, SocketFlags.None); + this.a((double)this.n); + } + catch (Exception arg_77_0) + { + Logging.LogUsefulException(arg_77_0); + this.e(); + } + } + + private void b(IAsyncResult A_0) + { + if (this.f) + { + return; + } + try + { + int num = this.e.EndReceive(A_0); + if (num > 0) + { + this.a((double)this.n); + this.d.Send(this.k, num, SocketFlags.None); + if (Analyzer.instance().Add(this.h, this.i, this.e, this.k, num, true)) + { + Analyzer.instance().Close(this.h, this.i, this.e); + } + this.m += num; + if (this.m <= 2097152) + { + this.e.BeginReceive(this.k, 11680, SocketFlags.None, new AsyncCallback(this.b), null); + } + else + { + this.b(); + } + } + else + { + this.e(); + } + } + catch (Exception arg_D3_0) + { + Logging.LogUsefulException(arg_D3_0); + this.e(); + } + } + + private void b() + { + bool flag = false; + byte[] buffer = new byte[11680]; + DateTime d = DateTime.Now; + while (!this.f) + { + try + { + int num = this.e.Receive(buffer, 11680, SocketFlags.None); + DateTime now = DateTime.Now; + if (this.e != null && this.e.IsClose) + { + flag = true; + break; + } + if (this.f) + { + break; + } + this.a((double)this.n); + if (num > 0) + { + this.d.Send(buffer, num, SocketFlags.None); + if (Analyzer.instance().Add(this.h, this.i, this.e, buffer, num, true)) + { + Analyzer.instance().Close(this.h, this.i, this.e); + } + if ((now - d).TotalSeconds > 5.0) + { + this.m = 0; + this.e.BeginReceive(this.k, 11680, SocketFlags.None, new AsyncCallback(this.b), null); + return; + } + d = now; + } + else + { + this.e(); + } + } + catch (Exception arg_113_0) + { + Logging.LogUsefulException(arg_113_0); + flag = true; + break; + } + } + if (flag) + { + this.e(); + return; + } + } + + private void a(IAsyncResult A_0) + { + if (this.f) + { + return; + } + try + { + int num = this.d.EndReceive(A_0); + if (num > 0) + { + this.a((double)this.n); + this.e.Send(this.l, num, SocketFlags.None); + if (Analyzer.instance().Add(this.h, this.i, this.e, this.l, num, false)) + { + Analyzer.instance().Close(this.h, this.i, this.e); + } + this.d.BeginReceive(this.l, 11680, SocketFlags.None, new AsyncCallback(this.a), null); + } + else + { + this.e(); + } + } + catch (Exception arg_B0_0) + { + Logging.LogUsefulException(arg_B0_0); + this.e(); + } + } + + private void a(ProxySocketTun A_0) + { + lock (this) + { + if (A_0 != null) + { + try + { + A_0.Shutdown(SocketShutdown.Both); + } + catch + { + } + try + { + A_0.Close(); + } + catch + { + } + } + } + } + + public void e() + { + lock (this) + { + if (this.f) + { + return; + } + this.f = true; + } + this.a(0.0); + Thread.Sleep(100); + Analyzer.instance().Close(this.h, this.i, this.e); + this.a(this.e); + this.a(this.d); + } + + public override void Shutdown() + { + new IHandler.InvokeHandler(this.a).BeginInvoke(null, null); + } + + [CompilerGenerated] + private void a() + { + this.e(); + } + } + + private const int a = 1; + + private const int b = 2; + + private const int c = 0; + + private Configuration d; + + public b(Configuration A_0) + { + this.d = A_0; + } + + public bool b(byte[] A_0, int A_1, Socket A_2) + { + return this.a(A_0, A_1, A_2, null); + } + + public bool a(byte[] A_0, int A_1, Socket A_2, string A_3) + { + if (this.a(A_0, A_1, A_2) > 0) + { + new b.a().a(this.d, A_0, A_1, A_2, A_3, false); + return true; + } + return false; + } + + public int a(byte[] A_0, int A_1, Socket A_2) + { + return 2; + } +} diff --git a/c.cs b/c.cs new file mode 100644 index 0000000..ff89c12 --- /dev/null +++ b/c.cs @@ -0,0 +1,401 @@ +using socks5.Controller; +using socks5.Model; +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + +internal class c +{ + private Configuration a; + + private byte[] b; + + private int c; + + private Socket d; + + private Socket e; + + private string f; + + protected const int g = 16384; + + protected byte[] h = new byte[32768]; + + public byte i; + + protected byte[] j; + + public c(Configuration A_0, byte[] A_1, int A_2, Socket A_3) + { + int arg_27_0 = ((IPEndPoint)A_3.LocalEndPoint).Port; + this.a = A_0; + this.b = A_1; + this.c = A_2; + this.d = A_3; + A_3.NoDelay = true; + this.g(); + } + + private void a(ref Socket A_0) + { + lock (this) + { + if (A_0 != null) + { + Socket socket = A_0; + A_0 = null; + try + { + socket.Shutdown(SocketShutdown.Both); + } + catch + { + } + try + { + socket.Close(); + } + catch + { + } + } + } + } + + private void h() + { + this.a(ref this.d); + this.a(ref this.e); + this.a = null; + } + + private bool a(Socket A_0, string A_1, string A_2) + { + return true; + } + + private void g() + { + try + { + if (this.c > 1) + { + if (this.b[0] == 5 && this.c >= 3) + { + this.f(); + } + else + { + this.h(); + } + } + else + { + this.h(); + } + } + catch (Exception arg_35_0) + { + Logging.LogUsefulException(arg_35_0); + this.h(); + } + } + + private void f() + { + byte[] expr_06 = new byte[2]; + expr_06[0] = 5; + byte[] array = expr_06; + if (this.b[0] != 5) + { + array = new byte[] + { + 0, + 91 + }; + Console.WriteLine("socks 4/5 protocol error"); + this.d.Send(array); + this.h(); + return; + } + bool flag = false; + bool flag2 = false; + bool flag3 = false; + for (int i = 0; i < (int)this.b[1]; i++) + { + if (this.b[2 + i] == 0) + { + flag = true; + flag3 = true; + } + else if (this.b[2 + i] == 2) + { + flag2 = true; + flag3 = true; + } + } + if (!flag3) + { + Console.WriteLine("Socks5 no acceptable auth method"); + this.h(); + return; + } + if (flag2 || !flag) + { + array[1] = 2; + this.d.Send(array); + this.e(); + return; + } + if (flag) + { + this.d.Send(array); + this.d(); + return; + } + Console.WriteLine("Socks5 Auth failed"); + this.h(); + } + + private void e() + { + try + { + if (this.d.Receive(this.h, 1024, SocketFlags.None) >= 3) + { + byte b = this.h[1]; + byte count = this.h[(int)(b + 2)]; + byte[] expr_34 = new byte[2]; + expr_34[0] = 1; + byte[] buffer = expr_34; + string @string = Encoding.UTF8.GetString(this.h, 2, (int)b); + string string2 = Encoding.UTF8.GetString(this.h, (int)(b + 3), (int)count); + if (this.a(this.d, @string, string2)) + { + this.d.Send(buffer); + this.d(); + } + } + else + { + Console.WriteLine("failed to recv data in HandshakeAuthReceiveCallback"); + this.h(); + } + } + catch (Exception arg_9A_0) + { + Logging.LogUsefulException(arg_9A_0); + this.h(); + } + } + + private void d() + { + try + { + int num = this.d.Receive(this.h, 5, SocketFlags.None); + if (num >= 5) + { + this.i = this.h[1]; + this.j = new byte[num - 3]; + Array.Copy(this.h, 3, this.j, 0, this.j.Length); + int num2 = 0; + if (this.j[0] == 1) + { + num2 = 3; + } + else if (this.j[0] == 4) + { + num2 = 15; + } + else if (this.j[0] == 3) + { + num2 = (int)this.j[1]; + } + if (num2 == 0) + { + throw new Exception("Wrong socks5 addr type"); + } + this.b(num2 + 2); + } + else + { + Console.WriteLine("failed to recv data in HandshakeReceive2Callback"); + this.h(); + } + } + catch (Exception arg_B2_0) + { + Logging.LogUsefulException(arg_B2_0); + this.h(); + } + } + + private void b(int A_0) + { + try + { + int num = this.d.Receive(this.h, A_0, SocketFlags.None); + if (num > 0) + { + Array.Resize(ref this.j, this.j.Length + num); + Array.Copy(this.h, 0, this.j, this.j.Length - num, num); + if (this.i == 3) + { + this.a(num); + } + else + { + this.f = "socks5"; + this.b(); + } + } + else + { + Console.WriteLine("failed to recv data in HandshakeReceive3Callback"); + this.h(); + } + } + catch (Exception arg_81_0) + { + Logging.LogUsefulException(arg_81_0); + this.h(); + } + } + + private void a(int A_0) + { + bool flag = this.d.AddressFamily == AddressFamily.InterNetworkV6; + int num = 0; + if (A_0 >= 9) + { + flag = (this.j[0] == 4); + if (!flag) + { + num = (int)this.j[5] * 256 + (int)this.j[6]; + } + else + { + num = (int)this.j[17] * 256 + (int)this.j[18]; + } + } + if (!flag) + { + this.j = new byte[7]; + this.j[0] = 9; + this.j[5] = (byte)(num / 256); + this.j[6] = (byte)(num % 256); + } + else + { + this.j = new byte[19]; + this.j[0] = 12; + this.j[17] = (byte)(num / 256); + this.j[18] = (byte)(num % 256); + } + int i = 0; + IPAddress iPAddress = flag ? IPAddress.IPv6Any : IPAddress.Any; + this.e = new Socket(iPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); + while (i < 65536) + { + try + { + this.e.Bind(new IPEndPoint(iPAddress, i)); + break; + } + catch (Exception) + { + } + i++; + } + i = ((IPEndPoint)this.e.LocalEndPoint).Port; + if (!flag) + { + byte[] array = new byte[] + { + 5, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + (byte)(i / 256), + (byte)(i % 256) + }; + Array.Copy(((IPEndPoint)this.d.LocalEndPoint).Address.GetAddressBytes(), 0, array, 4, 4); + this.d.Send(array); + this.b(); + return; + } + byte[] array2 = new byte[] + { + 5, + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + (byte)(i / 256), + (byte)(i % 256) + }; + Array.Copy(((IPEndPoint)this.d.LocalEndPoint).Address.GetAddressBytes(), 0, array2, 4, 16); + this.d.Send(array2); + this.b(); + } + + private void c() + { + if (this.d.AddressFamily == AddressFamily.InterNetwork) + { + byte[] expr_15 = new byte[10]; + expr_15[0] = 5; + expr_15[3] = 1; + byte[] buffer = expr_15; + this.d.Send(buffer); + return; + } + byte[] expr_33 = new byte[22]; + expr_33[0] = 5; + expr_33[3] = 4; + byte[] buffer2 = expr_33; + this.d.Send(buffer2); + } + + private void b() + { + int arg_15_0 = ((IPEndPoint)this.d.LocalEndPoint).Port; + if (this.e == null) + { + new b(this.a).a(this.j, this.j.Length, this.d, this.f); + } + this.a(); + this.h(); + } + + private void a() + { + this.b = null; + this.d = null; + this.e = null; + this.h = null; + this.j = null; + } +} diff --git a/d.cs b/d.cs new file mode 100644 index 0000000..66290f5 --- /dev/null +++ b/d.cs @@ -0,0 +1,317 @@ +using socks5.Controller; +using socks5.Model; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Timers; + +internal class d +{ + public interface b + { + bool a(byte[] A_0, int A_1, Socket A_2); + } + + [CompilerGenerated] + private sealed class a + { + public Socket a; + + public d b; + + internal void d(object A_0, ElapsedEventArgs A_1) + { + this.b.a(A_0, A_1, this.a); + } + + internal void c(object A_0, ElapsedEventArgs A_1) + { + this.b.a(A_0, A_1, this.a); + } + } + + private Configuration a; + + private bool b; + + private string c; + + private Socket d; + + private Socket e; + + private bool f; + + private IList g; + + protected Timer h; + + protected object i = new object(); + + public d(IList A_0) + { + this.g = A_0; + this.f = false; + } + + public IList b() + { + return this.g; + } + + private bool a(int A_0) + { + try + { + IPEndPoint[] activeTcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(); + for (int i = 0; i < activeTcpListeners.Length; i++) + { + if (activeTcpListeners[i].Port == A_0) + { + return true; + } + } + } + catch + { + } + return false; + } + + public bool a(Configuration A_0) + { + try + { + if (this.b != A_0.shareOverLan || this.d == null || ((IPEndPoint)this.d.LocalEndPoint).Port != A_0.localPort) + { + return true; + } + } + catch (Exception) + { + } + return false; + } + + public void a(Configuration A_0, int A_1) + { + this.a = A_0; + this.b = A_0.shareOverLan; + this.c = ""; + this.f = false; + int num = (A_1 == 0) ? this.a.localPort : A_1; + if (this.a(num)) + { + throw new Exception("Port already in use"); + } + try + { + bool arg_6D_0 = true; + this.d = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + this.d.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + if (arg_6D_0) + { + try + { + this.e = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); + this.e.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + } + catch + { + this.e = null; + } + } + IPEndPoint localEP = new IPEndPoint(IPAddress.Any, num); + IPEndPoint localEP2 = new IPEndPoint(IPAddress.IPv6Any, num); + if (this.e != null) + { + this.e.Bind(localEP2); + this.e.Listen(1024); + } + this.d.Bind(localEP); + this.d.Listen(1024); + Console.WriteLine("socks5 started on port " + num.ToString()); + this.d.BeginAccept(new AsyncCallback(this.b), this.d); + if (this.e != null) + { + this.e.BeginAccept(new AsyncCallback(this.b), this.e); + } + } + catch (SocketException arg_154_0) + { + Logging.LogUsefulException(arg_154_0); + if (this.d != null) + { + this.d.Close(); + this.d = null; + } + if (this.e != null) + { + this.e.Close(); + this.e = null; + } + throw; + } + } + + public void a() + { + this.a(0.0, null); + this.f = true; + if (this.d != null) + { + this.d.Close(); + this.d = null; + } + if (this.e != null) + { + this.e.Close(); + this.e = null; + } + } + + private void a(double A_0, Socket A_1) + { + d.a a = new d.a(); + a.b = this; + a.a = A_1; + if (A_0 <= 0.0 && this.h == null) + { + return; + } + object obj = this.i; + lock (obj) + { + if (A_0 <= 0.0) + { + if (this.h != null) + { + this.h.Enabled = false; + this.h.Elapsed -= new ElapsedEventHandler(a.d); + this.h.Dispose(); + this.h = null; + } + } + else if (this.h == null) + { + this.h = new Timer(A_0 * 1000.0); + this.h.Elapsed += new ElapsedEventHandler(a.c); + this.h.Start(); + } + else + { + this.h.Interval = A_0 * 1000.0; + this.h.Stop(); + this.h.Start(); + } + } + } + + private void a(object A_0, ElapsedEventArgs A_1, Socket A_2) + { + if (this.h == null) + { + return; + } + try + { + A_2.BeginAccept(new AsyncCallback(this.b), A_2); + this.a(0.0, A_2); + } + catch (ObjectDisposedException) + { + } + catch (Exception arg_34_0) + { + Logging.LogUsefulException(arg_34_0); + this.a(5.0, A_2); + } + } + + public void b(IAsyncResult A_0) + { + if (this.f) + { + return; + } + Socket socket = (Socket)A_0.AsyncState; + try + { + Socket socket2 = socket.EndAccept(A_0); + if (!this.b && !global::a.b(socket2)) + { + socket2.Shutdown(SocketShutdown.Both); + socket2.Close(); + } + if ((this.c ?? "").Length == 0 && !global::a.a(socket2)) + { + socket2.Shutdown(SocketShutdown.Both); + socket2.Close(); + } + else + { + byte[] array = new byte[4096]; + object[] state = new object[] + { + socket2, + array + }; + socket2.BeginReceive(array, 0, array.Length, SocketFlags.None, new AsyncCallback(this.a), state); + } + } + catch (ObjectDisposedException) + { + } + catch (Exception arg_A0_0) + { + Console.WriteLine(arg_A0_0); + } + finally + { + try + { + socket.BeginAccept(new AsyncCallback(this.b), socket); + } + catch (ObjectDisposedException) + { + } + catch (Exception arg_C1_0) + { + Logging.LogUsefulException(arg_C1_0); + this.a(5.0, socket); + } + } + } + + private void a(IAsyncResult A_0) + { + object[] expr_0B = (object[])A_0.AsyncState; + Socket socket = (Socket)expr_0B[0]; + byte[] a_ = (byte[])expr_0B[1]; + try + { + int a_2 = socket.EndReceive(A_0); + using (IEnumerator enumerator = this.g.GetEnumerator()) + { + while (enumerator.MoveNext()) + { + if (enumerator.Current.a(a_, a_2, socket)) + { + return; + } + } + } + socket.Shutdown(SocketShutdown.Both); + socket.Close(); + } + catch (Exception arg_67_0) + { + Console.WriteLine(arg_67_0); + socket.Shutdown(SocketShutdown.Both); + socket.Close(); + } + } +} diff --git a/e.cs b/e.cs new file mode 100644 index 0000000..3fd9d09 --- /dev/null +++ b/e.cs @@ -0,0 +1,19 @@ +using System; + +internal class e : IComparable +{ + public long a; + + public int b; + + public e(int A_0, long A_1) + { + this.a = A_1; + this.b = A_0; + } + + public int CompareTo(object obj) + { + return this.a.CompareTo(((e)obj).a); + } +} diff --git a/f.cs b/f.cs new file mode 100644 index 0000000..f7de9ed --- /dev/null +++ b/f.cs @@ -0,0 +1,137 @@ +using socks5.Controller; +using socks5.Model; +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Threading; + +internal class f +{ + private class a : d.b + { + private delegate void b(); + + [CompilerGenerated] + private sealed class a + { + public byte[] a; + + public int b; + + public Socket c; + + public f.a d; + + internal void e() + { + new c(this.d.a, this.a, this.b, this.c); + } + } + + private Configuration a; + + public a(Configuration A_0) + { + this.a = A_0; + } + + protected bool a(byte[] A_0, int A_1) + { + return A_1 >= 2 && (A_0[0] == 5 || A_0[0] == 4 || (A_1 > 8 && A_0[0] == 67 && A_0[1] == 79 && A_0[2] == 78 && A_0[3] == 78 && A_0[4] == 69 && A_0[5] == 67 && A_0[6] == 84 && A_0[7] == 32)); + } + + public bool a(byte[] A_0, int A_1, Socket A_2) + { + f.a.a a = new f.a.a(); + a.d = this; + a.a = A_0; + a.b = A_1; + a.c = A_2; + if (!this.a(a.a, a.b)) + { + return false; + } + new f.a.b(a.e).BeginInvoke(null, null); + return true; + } + } + + private d a; + + private Configuration b; + + private bool c; + + protected void b() + { + this.b = new Configuration(); + bool flag = false; + for (int i = 1; i <= 5; i++) + { + try + { + if (this.a != null && !this.a.a(this.b)) + { + f.a value = new f.a(this.b); + this.a.b()[0] = value; + } + else + { + if (this.a != null) + { + this.a.a(); + this.a = null; + } + f.a item = new f.a(this.b); + this.a = new d(new List + { + item + }); + this.a.a(this.b, 0); + } + break; + } + catch (Exception ex) + { + if (ex is SocketException && ((SocketException)ex).SocketErrorCode == SocketError.AccessDenied) + { + ex = new Exception("Port already in use" + string.Format(" {0}", this.b.localPort), ex); + } + Logging.LogUsefulException(ex); + if (!flag) + { + break; + } + Thread.Sleep(1000 * i * i); + if (this.a != null) + { + this.a.a(); + this.a = null; + } + } + } + global::a.c(); + } + + public void a() + { + if (this.c) + { + return; + } + this.c = true; + if (this.a != null) + { + this.a.a(); + } + } + + private static void a(string[] A_0) + { + f expr_05 = new f(); + expr_05.b(); + Console.ReadLine(); + expr_05.a(); + } +} diff --git a/g.cs b/g.cs new file mode 100644 index 0000000..5c43e91 --- /dev/null +++ b/g.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; + +internal class g +{ + private string a; + + private long[] b = new long[2049]; + + private long[] c = new long[2049]; + + public int d; + + public int e; + + public int f; + + public int g; + + public int h = 500; + + private int i; + + private int j; + + private int k; + + public g(string A_0) + { + this.a = A_0; + } + + public void a(h A_0) + { + for (int i = 0; i <= 2048; i++) + { + this.b[i] += A_0.b[i]; + this.c[i] += A_0.c[i]; + A_0.b[i] = 0L; + A_0.c[i] = 0L; + } + this.d += A_0.d; + A_0.d = 0; + this.e += A_0.e; + A_0.e = 0; + this.f++; + if (A_0.h) + { + this.g++; + } + bool flag = false; + int num = 0; + int num2 = 0; + if (this.d + this.e > this.h && this.f >= 5) + { + flag = true; + this.h += 200; + int arg_118_0 = (int)((long)this.d - this.b[2048]); + int num3 = (int)((long)this.e - this.c[2048]); + if (arg_118_0 >= 100 && num3 >= 100) + { + int[] array = new int[200]; + int[] array2 = new int[200]; + e[] array3 = new e[200]; + for (int j = 0; j < 200; j++) + { + array3[j] = new e(j, this.c[j]); + } + Array.Sort(array3); + int num4 = 199; + while (num4 > 170 && (array3[num4].a != array3[num4 - 1].a || array3[num4].a != array3[num4 - 2].a)) + { + array[array3[num4].b] = 1; + num4--; + } + for (int k = 0; k < 200; k++) + { + array3[k] = new e(k, this.b[k]); + } + Array.Sort(array3); + int num5 = 199; + while (num5 > 170 && (array3[num5].a != array3[num5 - 1].a || array3[num5].a != array3[num5 - 2].a)) + { + array2[array3[num5].b] = 1; + num5--; + } + List list = new List(); + for (int l = 38; l < 170; l++) + { + if (array[l] == 1 && array[l + 8] == 1 && this.b[l] > 0L) + { + list.Add(l); + } + } + if (list.Count > 0) + { + int num6 = list[0]; + if (list.Count < 6) + { + if (this.g < this.f / 1024 || this.g <= 1) + { + if (num6 == 38) + { + this.b("Remote [" + this.a + "] looks like a Shadowsocks Server"); + num2 = 1; + } + else if (num6 == 72) + { + this.b("Remote [" + this.a + "] looks like a Shadowsocks Server with AEAD cipher"); + num2 = 2; + } + else if (num6 == 44 && this.c[6] > (long)(num3 / 300)) + { + this.b("Remote [" + this.a + "] looks like a V2ray Server with vmess + stream cipher"); + num2 = 11; + } + else if (num6 == 56 && this.c[18] > (long)(num3 / 300)) + { + this.b("Remote [" + this.a + "] looks like a V2ray Server with vmess + AEAD cipher"); + num2 = 12; + } + else if (num6 == 52 && this.c[12] > (long)(num3 / 300)) + { + this.b("Remote [" + this.a + "] looks like a V2ray Server with vmess MUX + stream cipher"); + num2 = 13; + } + else if (num6 == 64 && this.c[24] > (long)(num3 / 300)) + { + this.b("Remote [" + this.a + "] looks like a V2ray Server with vmess MUX + AEAD cipher"); + num2 = 14; + } + } + else if (this.g > this.f / 2) + { + num = 1; + if (num6 == 43) + { + this.b("Remote [" + this.a + "] looks like a Shadowsocks Server with TLS obfs"); + } + else if (num6 == 77) + { + this.b("Remote [" + this.a + "] looks like a Shadowsocks Server with AEAD cipher & TLS obfs"); + } + } + } + } + } + } + if (num2 > 0) + { + if (num == this.j && num2 == this.k) + { + this.i++; + this.a(" by " + ((int)(100.0 - Math.Pow(0.4, (double)this.i) * 100.0)).ToString() + "%"); + } + else + { + this.i = 0; + this.j = num; + this.k = num2; + this.a(" by 20%"); + } + } + if (flag) + { + this.b = new long[2049]; + this.c = new long[2049]; + this.d = 0; + this.e = 0; + this.f = 0; + this.g = 0; + this.h = 500; + } + } + + private void b(string A_0) + { + Console.Write(string.Format("[{0}] {1}", DateTime.Now, A_0)); + } + + private void a(string A_0) + { + Console.WriteLine(A_0); + } +} diff --git a/h.cs b/h.cs new file mode 100644 index 0000000..435696b --- /dev/null +++ b/h.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; + +internal class h +{ + public const int a = 2048; + + public long[] b = new long[2049]; + + public long[] c = new long[2049]; + + public int d; + + public int e; + + private int f; + + private List g = new List(); + + public bool h; + + public bool f(byte[] A_0, int A_1) + { + this.d++; + if (A_1 > 2048) + { + A_1 = 2048; + } + this.b[A_1] += 1L; + return (this.d + this.e) % 100 == 0; + } + + public bool a(byte[] A_0, int A_1) + { + this.e++; + this.f++; + this.c[A_1] += 1L; + if (this.f == 1 && A_1 > 3 && A_0[0] == 22 && A_0[1] == 3 && A_0[2] == 1) + { + this.h = true; + } + return (this.d + this.e) % 100 == 0; + } +} diff --git a/socks5.Controller/Analyzer.cs b/socks5.Controller/Analyzer.cs new file mode 100644 index 0000000..b177393 --- /dev/null +++ b/socks5.Controller/Analyzer.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; + +namespace socks5.Controller +{ + public class Analyzer + { + private static Analyzer a = new Analyzer(); + + private Dictionary b = new Dictionary(); + + private Dictionary c = new Dictionary(); + + public static Analyzer instance() + { + return Analyzer.a; + } + + public bool Add(string remote_host, int remote_port, ProxySocketTun socket, byte[] buffer, int size, bool remote) + { + if (socket == null) + { + return false; + } + h h = null; + Dictionary obj = this.b; + lock (obj) + { + if (this.b.ContainsKey(socket)) + { + h = this.b[socket]; + } + else + { + h = new h(); + this.b[socket] = h; + } + } + if (remote) + { + return h.f(buffer, size); + } + return h.a(buffer, size); + } + + public void Close(string remote_host, int remote_port, ProxySocketTun socket) + { + if (socket != null) + { + h h = null; + Dictionary obj = this.b; + lock (obj) + { + if (this.b.ContainsKey(socket)) + { + h = this.b[socket]; + this.b.Remove(socket); + } + } + if (h != null) + { + g g = null; + Dictionary obj2 = this.c; + lock (obj2) + { + string text = remote_host + ":" + remote_port.ToString(); + if (this.c.ContainsKey(text)) + { + g = this.c[text]; + } + else + { + g = new g(text); + this.c[text] = g; + } + } + g.a(h); + } + } + } + } +} diff --git a/socks5.Controller/CallbackState.cs b/socks5.Controller/CallbackState.cs new file mode 100644 index 0000000..0877c62 --- /dev/null +++ b/socks5.Controller/CallbackState.cs @@ -0,0 +1,15 @@ +using System; + +namespace socks5.Controller +{ + public class CallbackState + { + public byte[] buffer; + + public int size; + + public int protocol_size; + + public object state; + } +} diff --git a/socks5.Controller/IHandler.cs b/socks5.Controller/IHandler.cs new file mode 100644 index 0000000..f99722f --- /dev/null +++ b/socks5.Controller/IHandler.cs @@ -0,0 +1,11 @@ +using System; + +namespace socks5.Controller +{ + public abstract class IHandler + { + public delegate void InvokeHandler(); + + public abstract void Shutdown(); + } +} diff --git a/socks5.Controller/LogLevel.cs b/socks5.Controller/LogLevel.cs new file mode 100644 index 0000000..02388db --- /dev/null +++ b/socks5.Controller/LogLevel.cs @@ -0,0 +1,13 @@ +using System; + +namespace socks5.Controller +{ + public enum LogLevel + { + Debug, + Info, + Warn, + Error, + Assert + } +} diff --git a/socks5.Controller/Logging.cs b/socks5.Controller/Logging.cs new file mode 100644 index 0000000..83652db --- /dev/null +++ b/socks5.Controller/Logging.cs @@ -0,0 +1,249 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Net.Sockets; + +namespace socks5.Controller +{ + public class Logging + { + public static string LogFile; + + public static string LogFilePath; + + public static string LogFileName; + + protected static string date; + + private static FileStream a; + + private static StreamWriterWithTimestamp b; + + private static object c = new object(); + + public static bool OpenLogFile() + { + bool result; + try + { + Logging.a(); + string text = Path.Combine(Path.GetDirectoryName(global::a.a()), "temp"); + Logging.LogFilePath = text; + if (!Directory.Exists(text)) + { + Directory.CreateDirectory(text); + } + string str = DateTime.Now.ToString("yyyy-MM"); + Logging.LogFileName = "shadowsocks_" + str + ".log"; + Logging.LogFile = Path.Combine(text, Logging.LogFileName); + Logging.a = new FileStream(Logging.LogFile, FileMode.Append); + Logging.b = new StreamWriterWithTimestamp(Logging.a); + Logging.b.AutoFlush = true; + Console.SetError(Logging.b); + Logging.date = str; + result = true; + } + catch (IOException arg_A5_0) + { + Console.WriteLine(arg_A5_0.ToString()); + result = false; + } + return result; + } + + private static void a() + { + StreamWriterWithTimestamp expr_05 = Logging.b; + if (expr_05 != null) + { + expr_05.Dispose(); + } + FileStream expr_15 = Logging.a; + if (expr_15 != null) + { + expr_15.Dispose(); + } + Logging.b = null; + Logging.a = null; + } + + public static void Clear() + { + Logging.a(); + if (Logging.LogFile != null) + { + File.Delete(Logging.LogFile); + } + Logging.OpenLogFile(); + } + + public static void Error(object o) + { + Logging.Log(LogLevel.Error, o); + } + + public static void Info(object o) + { + Logging.Log(LogLevel.Info, o); + } + + [Conditional("DEBUG")] + public static void Debug(object o) + { + Logging.Log(LogLevel.Debug, o); + } + + private static string a(StackFrame[] A_0) + { + string text = string.Empty; + for (int i = 0; i < A_0.Length; i++) + { + StackFrame stackFrame = A_0[i]; + text += string.Format("{0}\r\n", stackFrame.GetMethod().ToString()); + } + return text; + } + + protected static void UpdateLogFile() + { + if (DateTime.Now.ToString("yyyy-MM") != Logging.date) + { + object obj = Logging.c; + lock (obj) + { + if (DateTime.Now.ToString("yyyy-MM") != Logging.date) + { + Logging.OpenLogFile(); + } + } + } + } + + public static void LogUsefulException(Exception e) + { + Logging.UpdateLogFile(); + if (e is SocketException) + { + SocketException ex = (SocketException)e; + if (ex.SocketErrorCode != SocketError.ConnectionAborted && ex.SocketErrorCode != SocketError.ConnectionReset && ex.SocketErrorCode != SocketError.NotConnected && ex.SocketErrorCode != (SocketError)(-2147467259) && ex.SocketErrorCode != SocketError.Shutdown && ex.SocketErrorCode != SocketError.Interrupted) + { + Logging.Error(e); + return; + } + } + else + { + Logging.Error(e); + } + } + + public static bool LogSocketException(string remarks, string server, Exception e) + { + Logging.UpdateLogFile(); + if (e is NullReferenceException) + { + return true; + } + if (e is ObjectDisposedException) + { + return true; + } + if (!(e is SocketException)) + { + return false; + } + SocketException ex = (SocketException)e; + if (ex.SocketErrorCode == (SocketError)(-2147467259)) + { + return true; + } + if (ex.ErrorCode == 11004) + { + Logging.Log(LogLevel.Warn, string.Concat(new string[] + { + "Proxy server [", + remarks, + "(", + server, + ")] DNS lookup failed" + })); + return true; + } + if (ex.SocketErrorCode == SocketError.HostNotFound) + { + Logging.Log(LogLevel.Warn, string.Concat(new string[] + { + "Proxy server [", + remarks, + "(", + server, + ")] Host not found" + })); + return true; + } + if (ex.SocketErrorCode == SocketError.ConnectionRefused) + { + Logging.Log(LogLevel.Warn, string.Concat(new string[] + { + "Proxy server [", + remarks, + "(", + server, + ")] connection refused" + })); + return true; + } + if (ex.SocketErrorCode == SocketError.NetworkUnreachable) + { + Logging.Log(LogLevel.Warn, string.Concat(new string[] + { + "Proxy server [", + remarks, + "(", + server, + ")] network unreachable" + })); + return true; + } + if (ex.SocketErrorCode == SocketError.TimedOut) + { + return true; + } + if (ex.SocketErrorCode == SocketError.Shutdown) + { + return true; + } + Logging.Log(LogLevel.Info, string.Concat(new string[] + { + "Proxy server [", + remarks, + "(", + server, + ")] ", + Convert.ToString(ex.SocketErrorCode), + ":", + ex.Message + })); + return true; + } + + public static void Log(LogLevel level, object s) + { + Logging.UpdateLogFile(); + string[] array = new string[] + { + "Debug", + "Info", + "Warn", + "Error", + "Assert" + }; + Console.Error.WriteLine(string.Format("[{0}] {1}", array[(int)level], s)); + } + + [Conditional("DEBUG")] + public static void LogBin(LogLevel level, string info, byte[] data, int length) + { + } + } +} diff --git a/socks5.Controller/ProxySocketTun.cs b/socks5.Controller/ProxySocketTun.cs new file mode 100644 index 0000000..389c648 --- /dev/null +++ b/socks5.Controller/ProxySocketTun.cs @@ -0,0 +1,391 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace socks5.Controller +{ + public 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 = 2920; + + private byte[] a = new byte[2920]; + + private byte[] b = new byte[5840]; + + protected bool _close; + + public bool IsClose + { + get + { + return this._close; + } + } + + public bool GoS5Proxy + { + get + { + return this._proxy; + } + set + { + this._proxy = value; + } + } + + public AddressFamily AddressFamily + { + get + { + return this._socket.AddressFamily; + } + } + + public int Available + { + get + { + return this._socket.Available; + } + } + + public ProxySocketTun(Socket socket) + { + this._socket = socket; + } + + public ProxySocketTun(AddressFamily af, SocketType type, ProtocolType protocol) + { + this._socket = new Socket(af, type, protocol); + } + + public Socket GetSocket() + { + return this._socket; + } + + public void Shutdown(SocketShutdown how) + { + this._socket.Shutdown(how); + } + + public void Close() + { + this._socket.Close(); + this._socket = null; + this.a = null; + this.b = null; + } + + public IAsyncResult BeginConnect(EndPoint ep, AsyncCallback callback, object state) + { + this._close = false; + this._socketEndPoint = ep; + return this._socket.BeginConnect(ep, callback, state); + } + + public void EndConnect(IAsyncResult ar) + { + this._socket.EndConnect(ar); + } + + public int Receive(byte[] buffer, int size, SocketFlags flags) + { + return this._socket.Receive(buffer, size, SocketFlags.None); + } + + public IAsyncResult BeginReceive(byte[] buffer, int size, SocketFlags flags, AsyncCallback callback, object state) + { + CallbackState callbackState = new CallbackState(); + callbackState.buffer = buffer; + callbackState.size = size; + callbackState.state = state; + return this._socket.BeginReceive(buffer, 0, size, flags, callback, callbackState); + } + + public int EndReceive(IAsyncResult ar) + { + int num = this._socket.EndReceive(ar); + if (num > 0) + { + ((CallbackState)ar.AsyncState).size = num; + return num; + } + this._close = true; + return num; + } + + public int SendAll(byte[] buffer, int size, SocketFlags flags) + { + int num; + for (int i = this._socket.Send(buffer, size, SocketFlags.None); i < size; i += num) + { + num = this._socket.Send(buffer, i, size - i, SocketFlags.None); + } + return size; + } + + public virtual int Send(byte[] buffer, int size, SocketFlags flags) + { + return this.SendAll(buffer, size, SocketFlags.None); + } + + public int BeginSend(byte[] buffer, int size, SocketFlags flags, AsyncCallback callback, object state) + { + CallbackState callbackState = new CallbackState(); + callbackState.size = size; + callbackState.state = state; + this._socket.BeginSend(buffer, 0, size, SocketFlags.None, callback, callbackState); + return size; + } + + public int EndSend(IAsyncResult ar) + { + return this._socket.EndSend(ar); + } + + public IAsyncResult BeginReceiveFrom(byte[] buffer, int size, SocketFlags flags, ref EndPoint ep, AsyncCallback callback, object state) + { + CallbackState callbackState = new CallbackState(); + callbackState.buffer = buffer; + callbackState.size = size; + callbackState.state = state; + return this._socket.BeginReceiveFrom(buffer, 0, size, flags, ref ep, callback, callbackState); + } + + public int GetAsyncResultSize(IAsyncResult ar) + { + return ((CallbackState)ar.AsyncState).size; + } + + public byte[] GetAsyncResultBuffer(IAsyncResult ar) + { + return ((CallbackState)ar.AsyncState).buffer; + } + + public bool ConnectSocks5ProxyServer(string strRemoteHost, int iRemotePort, bool udp, string socks5RemoteUsername, string socks5RemotePassword) + { + int errorCode = 10054; + this._proxy = true; + byte[] array = new byte[10]; + array[0] = 5; + array[1] = ((socks5RemoteUsername.Length == 0) ? 1 : 2); + array[2] = 0; + array[3] = 2; + this._socket.Send(array, (int)(array[1] + 2), SocketFlags.None); + byte[] array2 = new byte[32]; + if (this._socket.Receive(array2, array2.Length, SocketFlags.None) < 2) + { + throw new SocketException(errorCode); + } + if (array2[0] != 5 || (array2[1] != 0 && array2[1] != 2)) + { + throw new SocketException(errorCode); + } + if (array2[1] != 0) + { + if (array2[1] != 2) + { + return false; + } + if (socks5RemoteUsername.Length == 0) + { + throw new SocketException(errorCode); + } + array = new byte[socks5RemoteUsername.Length + socks5RemotePassword.Length + 3]; + array[0] = 1; + array[1] = (byte)socks5RemoteUsername.Length; + for (int i = 0; i < socks5RemoteUsername.Length; i++) + { + array[2 + i] = (byte)socks5RemoteUsername[i]; + } + array[socks5RemoteUsername.Length + 2] = (byte)socks5RemotePassword.Length; + for (int j = 0; j < socks5RemotePassword.Length; j++) + { + array[socks5RemoteUsername.Length + 3 + j] = (byte)socks5RemotePassword[j]; + } + this._socket.Send(array, array.Length, SocketFlags.None); + this._socket.Receive(array2, array2.Length, SocketFlags.None); + if (array2[0] != 1 || array2[1] != 0) + { + throw new SocketException(10061); + } + } + if (!udp) + { + List list = new List(); + list.Add(5); + list.Add(1); + list.Add(0); + IPAddress iPAddress; + IPAddress.TryParse(strRemoteHost, out iPAddress); + if (iPAddress == null) + { + list.Add(3); + list.Add((byte)strRemoteHost.Length); + for (int k = 0; k < strRemoteHost.Length; k++) + { + list.Add((byte)strRemoteHost[k]); + } + } + else + { + byte[] addressBytes = iPAddress.GetAddressBytes(); + if (addressBytes.GetLength(0) > 4) + { + list.Add(4); + for (int l = 0; l < 16; l++) + { + list.Add(addressBytes[l]); + } + } + else + { + list.Add(1); + for (int m = 0; m < 4; m++) + { + list.Add(addressBytes[m]); + } + } + } + list.Add((byte)(iRemotePort / 256)); + list.Add((byte)(iRemotePort % 256)); + this._socket.Send(list.ToArray(), list.Count, SocketFlags.None); + if (this._socket.Receive(array2, array2.Length, SocketFlags.None) < 2 || array2[0] != 5 || array2[1] != 0) + { + throw new SocketException(errorCode); + } + return true; + } + else + { + List list2 = new List(); + list2.Add(5); + list2.Add(3); + list2.Add(0); + IPAddress iPAddress2 = ((IPEndPoint)this._socketEndPoint).Address; + byte[] addressBytes2 = iPAddress2.GetAddressBytes(); + if (addressBytes2.GetLength(0) > 4) + { + list2.Add(4); + for (int n = 0; n < 16; n++) + { + list2.Add(addressBytes2[n]); + } + } + else + { + list2.Add(1); + for (int num = 0; num < 4; num++) + { + list2.Add(addressBytes2[num]); + } + } + list2.Add(0); + list2.Add(0); + this._socket.Send(list2.ToArray(), list2.Count, SocketFlags.None); + this._socket.Receive(array2, array2.Length, SocketFlags.None); + if (array2[0] != 5 || array2[1] != 0) + { + throw new SocketException(errorCode); + } + byte[] array3; + int port; + if (array2[0] != 4) + { + array3 = new byte[4]; + Array.Copy(array2, 4, array3, 0, 4); + port = (int)array2[8] * 256 + (int)array2[9]; + } + else + { + array3 = new byte[16]; + Array.Copy(array2, 4, array3, 0, 16); + port = (int)array2[20] * 256 + (int)array2[21]; + } + iPAddress2 = new IPAddress(array3); + this._remoteUDPEndPoint = new IPEndPoint(iPAddress2, port); + return true; + } + } + + public void SetTcpServer(string server, int port) + { + this._proxy_server = server; + this._proxy_udp_port = port; + } + + public void SetUdpServer(string server, int port) + { + this._proxy_server = server; + this._proxy_udp_port = port; + } + + public void SetUdpEndPoint(IPEndPoint ep) + { + this._remoteUDPEndPoint = ep; + } + + public bool ConnectHttpProxyServer(string strRemoteHost, int iRemotePort, string socks5RemoteUsername, string socks5RemotePassword, string proxyUserAgent) + { + this._proxy = true; + IPAddress iPAddress; + IPAddress.TryParse(strRemoteHost, out iPAddress); + if (iPAddress != null) + { + strRemoteHost = iPAddress.ToString(); + } + string text = ((strRemoteHost.IndexOf(':') >= 0) ? ("[" + strRemoteHost + "]") : strRemoteHost) + ":" + iRemotePort.ToString(); + string str = Convert.ToBase64String(Encoding.UTF8.GetBytes(socks5RemoteUsername + ":" + socks5RemotePassword)); + string text2 = string.Concat(new string[] + { + "CONNECT ", + text, + " HTTP/1.0\r\nHost: ", + text, + "\r\n" + }); + if (!string.IsNullOrEmpty(proxyUserAgent)) + { + text2 = text2 + "User-Agent: " + proxyUserAgent + "\r\n"; + } + text2 += "Proxy-Connection: Keep-Alive\r\n"; + if (socks5RemoteUsername.Length > 0) + { + text2 = text2 + "Proxy-Authorization: Basic " + str + "\r\n"; + } + text2 += "\r\n"; + byte[] bytes = Encoding.UTF8.GetBytes(text2); + this._socket.Send(bytes, bytes.Length, SocketFlags.None); + byte[] array = new byte[1024]; + int num = this._socket.Receive(array, array.Length, SocketFlags.None); + if (num > 13) + { + string[] array2 = Encoding.UTF8.GetString(array, 0, num).Split(new char[] + { + ' ' + }); + if (array2.Length > 1 && array2[1] == "200") + { + return true; + } + } + return false; + } + } +} diff --git a/socks5.Controller/ProxySocketTunLocal.cs b/socks5.Controller/ProxySocketTunLocal.cs new file mode 100644 index 0000000..7bb43a4 --- /dev/null +++ b/socks5.Controller/ProxySocketTunLocal.cs @@ -0,0 +1,52 @@ +using System; +using System.Net.Sockets; +using System.Text; + +namespace socks5.Controller +{ + public class ProxySocketTunLocal : ProxySocketTun + { + public string local_sendback_protocol; + + public ProxySocketTunLocal(Socket socket) : base(socket) + { + } + + public ProxySocketTunLocal(AddressFamily af, SocketType type, ProtocolType protocol) : base(af, type, protocol) + { + } + + public override int Send(byte[] buffer, int size, SocketFlags flags) + { + if (this.local_sendback_protocol != null) + { + if (this.local_sendback_protocol == "http") + { + byte[] bytes = Encoding.UTF8.GetBytes("HTTP/1.1 200 Connection Established\r\n\r\n"); + this._socket.Send(bytes, bytes.Length, SocketFlags.None); + } + else if (this.local_sendback_protocol == "socks5") + { + if (this._socket.AddressFamily == AddressFamily.InterNetwork) + { + byte[] expr_67 = new byte[10]; + expr_67[0] = 5; + expr_67[3] = 1; + byte[] buffer2 = expr_67; + this._socket.Send(buffer2); + } + else + { + byte[] expr_86 = new byte[22]; + expr_86[0] = 5; + expr_86[3] = 4; + byte[] buffer3 = expr_86; + this._socket.Send(buffer3); + } + } + this.local_sendback_protocol = null; + } + return base.SendAll(buffer, size, SocketFlags.None); + } + } +} diff --git a/socks5.Controller/StreamWriterWithTimestamp.cs b/socks5.Controller/StreamWriterWithTimestamp.cs new file mode 100644 index 0000000..50cd33c --- /dev/null +++ b/socks5.Controller/StreamWriterWithTimestamp.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; + +namespace socks5.Controller +{ + public class StreamWriterWithTimestamp : StreamWriter + { + public StreamWriterWithTimestamp(Stream stream) : base(stream) + { + } + + private string a() + { + return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] "; + } + + public override void WriteLine(string value) + { + base.WriteLine(this.a() + value); + } + + public override void Write(string value) + { + base.Write(this.a() + value); + } + } +} diff --git a/socks5.Model/Configuration.cs b/socks5.Model/Configuration.cs new file mode 100644 index 0000000..d946319 --- /dev/null +++ b/socks5.Model/Configuration.cs @@ -0,0 +1,18 @@ +using System; + +namespace socks5.Model +{ + [Serializable] + public class Configuration + { + public bool shareOverLan; + + public int localPort; + + public Configuration() + { + this.localPort = 1081; + this.shareOverLan = true; + } + } +} diff --git a/socks5.Model/LRUCache.cs b/socks5.Model/LRUCache.cs new file mode 100644 index 0000000..c66b936 --- /dev/null +++ b/socks5.Model/LRUCache.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; + +namespace socks5.Model +{ + 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 = 3600) + { + this._sweep_time = sweep_time; + } + + public void SetTimeout(int time) + { + this._sweep_time = time; + } + + public bool isTimeout(K key) + { + object @lock = this._lock; + bool result; + lock (@lock) + { + if ((DateTime.Now - this._key_2_time[key]).TotalSeconds > (double)this._sweep_time) + { + result = true; + } + else + { + result = false; + } + } + return result; + } + + public bool ContainsKey(K key) + { + object @lock = this._lock; + bool result; + lock (@lock) + { + result = this._store.ContainsKey(key); + } + return result; + } + + public V Get(K key) + { + object @lock = this._lock; + V result; + lock (@lock) + { + if (this._store.ContainsKey(key)) + { + DateTime dateTime = this._key_2_time[key]; + this._key_2_time.Remove(key); + this._time_2_key.Remove(dateTime); + dateTime = DateTime.Now; + while (this._time_2_key.ContainsKey(dateTime)) + { + dateTime = dateTime.AddTicks(1L); + } + this._time_2_key[dateTime] = key; + this._key_2_time[key] = dateTime; + result = this._store[key]; + } + else + { + result = default(V); + } + } + return result; + } + + public V Set(K key, V val) + { + object @lock = this._lock; + lock (@lock) + { + DateTime dateTime; + if (this._store.ContainsKey(key)) + { + dateTime = this._key_2_time[key]; + this._key_2_time.Remove(key); + this._time_2_key.Remove(dateTime); + } + dateTime = DateTime.Now; + while (this._time_2_key.ContainsKey(dateTime)) + { + dateTime = dateTime.AddTicks(1L); + } + this._time_2_key[dateTime] = key; + this._key_2_time[key] = dateTime; + this._store[key] = val; + } + return val; + } + + public void Del(K key) + { + object @lock = this._lock; + lock (@lock) + { + if (this._store.ContainsKey(key)) + { + DateTime key2 = this._key_2_time[key]; + this._key_2_time.Remove(key); + this._time_2_key.Remove(key2); + this._store.Remove(key); + } + } + } + + public void Sweep() + { + object @lock = this._lock; + lock (@lock) + { + DateTime now = DateTime.Now; + int num = 0; + for (int i = 0; i < 100; i++) + { + bool flag2 = false; + using (Dictionary.Enumerator enumerator = this._time_2_key.GetEnumerator()) + { + if (enumerator.MoveNext()) + { + KeyValuePair current = enumerator.Current; + if ((now - current.Key).TotalSeconds < (double)this._sweep_time) + { + flag2 = true; + } + else + { + this._key_2_time.Remove(current.Value); + this._time_2_key.Remove(current.Key); + this._store.Remove(current.Value); + num++; + } + } + } + if (flag2) + { + break; + } + } + } + } + } +} diff --git a/socks5.csproj b/socks5.csproj new file mode 100644 index 0000000..7bf4b7b --- /dev/null +++ b/socks5.csproj @@ -0,0 +1,53 @@ + + + + {E804010C-28BA-4872-8D0B-8CEE06B446DC} + Debug + AnyCPU + Exe + socks5 + v4.0 + 4 + + + AnyCPU + + + bin\Debug\ + true + full + false + + + bin\Release\ + true + pdbonly + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file