Wv2hModule.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using AspNetTools;
  2. using System;
  3. using System.Configuration;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Runtime.InteropServices;
  9. using System.Threading;
  10. using System.Web;
  11. namespace Wv2h
  12. {
  13. public class Wv2hModule : IHttpModule
  14. {
  15. private static object _lock = new object();
  16. private static Process _process;
  17. private static IPEndPoint _listening;
  18. private static void Log(string info)
  19. {
  20. File.AppendAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "logs.log"), DateTime.Now + " " + info + Environment.NewLine);
  21. }
  22. public void Init(HttpApplication context)
  23. {
  24. Log("SshWsModule Init, OS:" + Environment.OSVersion.ToString());
  25. AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
  26. {
  27. Log(args.ExceptionObject?.ToString());
  28. };
  29. //start v2ray exe
  30. //get it's port
  31. var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data");
  32. lock (_lock)
  33. {
  34. if (_process == null || _process?.HasExited == true)
  35. {
  36. _process = new Process
  37. {
  38. StartInfo = {
  39. UseShellExecute = false,
  40. WorkingDirectory = dir,
  41. FileName = Path.Combine(dir, ConfigurationManager.AppSettings["exe"]),
  42. Arguments = "-config="+ConfigurationManager.AppSettings["cfg"]
  43. }
  44. };
  45. Log("Pending start process");
  46. _process.Start();
  47. var pid = _process.Id;
  48. Log("Process started, Pid:" + pid);
  49. Thread.Sleep(1000);
  50. var connections = ListenScan.GetAllTcpConnections();
  51. var listens = connections.Where(p => p.owningPid == pid).ToArray();
  52. _listening = new IPEndPoint(IPAddress.Loopback, listens.First().LocalPort);
  53. Log("Listening on " + _listening);
  54. }
  55. else
  56. {
  57. Log("Use exist process");
  58. }
  59. }
  60. //forward ws to v2
  61. context.PostMapRequestHandler += delegate
  62. {
  63. WebSocketForwardModule.ForwardCurrentContext("v2", ConfigurationManager.AppSettings["pass"], _listening, 1024 * int.Parse(ConfigurationManager.AppSettings["bsk"]));
  64. };
  65. }
  66. public void Dispose()
  67. {
  68. lock (_lock)
  69. {
  70. if (_process?.HasExited != true)
  71. {
  72. Log("Killing process " + _process?.Id);
  73. _process?.Kill();
  74. Log("Process Killed " + _process?.Id);
  75. }
  76. }
  77. }
  78. private static class ListenScan
  79. {
  80. public enum TCP_TABLE_CLASS : int
  81. {
  82. TCP_TABLE_BASIC_LISTENER,
  83. TCP_TABLE_BASIC_CONNECTIONS,
  84. TCP_TABLE_BASIC_ALL,
  85. TCP_TABLE_OWNER_PID_LISTENER,
  86. TCP_TABLE_OWNER_PID_CONNECTIONS,
  87. TCP_TABLE_OWNER_PID_ALL,
  88. TCP_TABLE_OWNER_MODULE_LISTENER,
  89. TCP_TABLE_OWNER_MODULE_CONNECTIONS,
  90. TCP_TABLE_OWNER_MODULE_ALL
  91. }
  92. [StructLayout(LayoutKind.Sequential)]
  93. public struct MIB_TCPROW_OWNER_PID
  94. {
  95. public uint state;
  96. public uint localAddr;
  97. public byte localPort1;
  98. public byte localPort2;
  99. public byte localPort3;
  100. public byte localPort4;
  101. public uint remoteAddr;
  102. public byte remotePort1;
  103. public byte remotePort2;
  104. public byte remotePort3;
  105. public byte remotePort4;
  106. public int owningPid;
  107. public ushort LocalPort
  108. {
  109. get
  110. {
  111. return BitConverter.ToUInt16(
  112. new byte[2] { localPort2, localPort1 }, 0);
  113. }
  114. }
  115. public ushort RemotePort
  116. {
  117. get
  118. {
  119. return BitConverter.ToUInt16(
  120. new byte[2] { remotePort2, remotePort1 }, 0);
  121. }
  122. }
  123. }
  124. [StructLayout(LayoutKind.Sequential)]
  125. public struct MIB_TCPTABLE_OWNER_PID
  126. {
  127. public uint dwNumEntries;
  128. private MIB_TCPROW_OWNER_PID table;
  129. }
  130. [DllImport("iphlpapi.dll", SetLastError = true)]
  131. private static extern uint GetExtendedTcpTable(IntPtr pTcpTable,
  132. ref int dwOutBufLen,
  133. bool sort,
  134. int ipVersion,
  135. TCP_TABLE_CLASS tblClass,
  136. int reserved);
  137. public static MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
  138. {
  139. MIB_TCPROW_OWNER_PID[] tTable;
  140. int AF_INET = 2; // IP_v4
  141. int buffSize = 0;
  142. // how much memory do we need?
  143. uint ret = GetExtendedTcpTable(IntPtr.Zero,
  144. ref buffSize,
  145. true,
  146. AF_INET,
  147. TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
  148. 0);
  149. if (ret != 0 && ret != 122) // 122 insufficient buffer size
  150. throw new Exception("bad ret on check " + ret);
  151. IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
  152. try
  153. {
  154. ret = GetExtendedTcpTable(buffTable,
  155. ref buffSize,
  156. true,
  157. AF_INET,
  158. TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
  159. 0);
  160. if (ret != 0)
  161. throw new Exception("bad ret " + ret);
  162. // get the number of entries in the table
  163. MIB_TCPTABLE_OWNER_PID tab =
  164. (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(
  165. buffTable,
  166. typeof(MIB_TCPTABLE_OWNER_PID));
  167. IntPtr rowPtr = (IntPtr)((long)buffTable +
  168. Marshal.SizeOf(tab.dwNumEntries));
  169. tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];
  170. for (int i = 0; i < tab.dwNumEntries; i++)
  171. {
  172. MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal
  173. .PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
  174. tTable[i] = tcpRow;
  175. // next entry
  176. rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
  177. }
  178. }
  179. finally
  180. {
  181. // Free the Memory
  182. Marshal.FreeHGlobal(buffTable);
  183. }
  184. return tTable;
  185. }
  186. }
  187. }
  188. }