Wv2hModule.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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("WsModule Init, OS:" + Environment.OSVersion);
  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(
  64. ConfigurationManager.AppSettings["key"],
  65. ConfigurationManager.AppSettings["value"],
  66. _listening, 1024 * int.Parse(ConfigurationManager.AppSettings["bsk"]));
  67. };
  68. }
  69. public void Dispose()
  70. {
  71. Log("WsModule Dispose");
  72. lock (_lock)
  73. {
  74. if (_process?.HasExited != true)
  75. {
  76. Log("Killing process " + _process?.Id);
  77. _process?.Kill();
  78. Log("Process Killed " + _process?.Id);
  79. }
  80. }
  81. }
  82. private static class ListenScan
  83. {
  84. public enum TCP_TABLE_CLASS : int
  85. {
  86. TCP_TABLE_BASIC_LISTENER,
  87. TCP_TABLE_BASIC_CONNECTIONS,
  88. TCP_TABLE_BASIC_ALL,
  89. TCP_TABLE_OWNER_PID_LISTENER,
  90. TCP_TABLE_OWNER_PID_CONNECTIONS,
  91. TCP_TABLE_OWNER_PID_ALL,
  92. TCP_TABLE_OWNER_MODULE_LISTENER,
  93. TCP_TABLE_OWNER_MODULE_CONNECTIONS,
  94. TCP_TABLE_OWNER_MODULE_ALL
  95. }
  96. [StructLayout(LayoutKind.Sequential)]
  97. public struct MIB_TCPROW_OWNER_PID
  98. {
  99. public uint state;
  100. public uint localAddr;
  101. public byte localPort1;
  102. public byte localPort2;
  103. public byte localPort3;
  104. public byte localPort4;
  105. public uint remoteAddr;
  106. public byte remotePort1;
  107. public byte remotePort2;
  108. public byte remotePort3;
  109. public byte remotePort4;
  110. public int owningPid;
  111. public ushort LocalPort
  112. {
  113. get
  114. {
  115. return BitConverter.ToUInt16(
  116. new byte[2] { localPort2, localPort1 }, 0);
  117. }
  118. }
  119. public ushort RemotePort
  120. {
  121. get
  122. {
  123. return BitConverter.ToUInt16(
  124. new byte[2] { remotePort2, remotePort1 }, 0);
  125. }
  126. }
  127. }
  128. [StructLayout(LayoutKind.Sequential)]
  129. public struct MIB_TCPTABLE_OWNER_PID
  130. {
  131. public uint dwNumEntries;
  132. private MIB_TCPROW_OWNER_PID table;
  133. }
  134. [DllImport("iphlpapi.dll", SetLastError = true)]
  135. private static extern uint GetExtendedTcpTable(IntPtr pTcpTable,
  136. ref int dwOutBufLen,
  137. bool sort,
  138. int ipVersion,
  139. TCP_TABLE_CLASS tblClass,
  140. int reserved);
  141. public static MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
  142. {
  143. MIB_TCPROW_OWNER_PID[] tTable;
  144. int AF_INET = 2; // IP_v4
  145. int buffSize = 0;
  146. // how much memory do we need?
  147. uint ret = GetExtendedTcpTable(IntPtr.Zero,
  148. ref buffSize,
  149. true,
  150. AF_INET,
  151. TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
  152. 0);
  153. if (ret != 0 && ret != 122) // 122 insufficient buffer size
  154. throw new Exception("bad ret on check " + ret);
  155. IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
  156. try
  157. {
  158. ret = GetExtendedTcpTable(buffTable,
  159. ref buffSize,
  160. true,
  161. AF_INET,
  162. TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
  163. 0);
  164. if (ret != 0)
  165. throw new Exception("bad ret " + ret);
  166. // get the number of entries in the table
  167. MIB_TCPTABLE_OWNER_PID tab =
  168. (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(
  169. buffTable,
  170. typeof(MIB_TCPTABLE_OWNER_PID));
  171. IntPtr rowPtr = (IntPtr)((long)buffTable +
  172. Marshal.SizeOf(tab.dwNumEntries));
  173. tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];
  174. for (int i = 0; i < tab.dwNumEntries; i++)
  175. {
  176. MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal
  177. .PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
  178. tTable[i] = tcpRow;
  179. // next entry
  180. rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
  181. }
  182. }
  183. finally
  184. {
  185. // Free the Memory
  186. Marshal.FreeHGlobal(buffTable);
  187. }
  188. return tTable;
  189. }
  190. }
  191. }
  192. }