SshWsModule.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using AspNetTools;
  2. using FxSsh;
  3. using FxSsh.Services;
  4. using MiniTerm;
  5. using System;
  6. using System.Configuration;
  7. using System.IO;
  8. using System.Net;
  9. using System.Net.Sockets;
  10. using System.Reflection;
  11. using System.Web;
  12. namespace WebTerminalServer
  13. {
  14. public class SshWsModule : IHttpModule
  15. {
  16. private SshServer _server;
  17. private IPEndPoint _listenEndPoint;
  18. private static void Log(string info)
  19. {
  20. File.AppendAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "logs.log"), 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. //Create ssh server with available port
  30. _server = new SshServer(new StartingInfo(IPAddress.Loopback, 0, "SSH-2"));
  31. _server.AddHostKey("ssh-rsa", ConfigurationManager.AppSettings["SshHostKey"]);
  32. _server.ConnectionAccepted += (s2, e2) =>
  33. {
  34. e2.ServiceRegistered += (s1, e1) =>
  35. {
  36. if (e1 is UserauthService)
  37. {
  38. var service = (UserauthService)e1;
  39. service.Userauth += (s, e) =>
  40. {
  41. e.Result = true;
  42. };
  43. }
  44. else if (e1 is ConnectionService service)
  45. {
  46. int w = 0, h = 0;
  47. Terminal terminal = null;
  48. service.EnvReceived += (s, e) => Console.WriteLine("Received environment variable {0}:{1}", e.Name, e.Value); ;
  49. service.PtyReceived += (s, e) =>
  50. {
  51. w = (int)e.WidthChars;
  52. h = (int)e.HeightRows;
  53. };
  54. service.WindowChange += (sender, args) =>
  55. {
  56. terminal?.ChangeWindowSize((short)args.WidthColumns, (short)args.HeightRows);
  57. };
  58. service.CommandOpened += (s, e) =>
  59. {
  60. Console.WriteLine($"Channel {e.Channel.ServerChannelId} runs {e.ShellType}: \"{e.CommandText}\".");
  61. var allow = true; // func(e.ShellType, e.CommandText, e.AttachedUserauthArgs);
  62. if (!allow) return;
  63. if (e.ShellType == "shell")
  64. {
  65. // requirements: Windows 10 RedStone 5, 1809
  66. // also, you can call powershell.exe
  67. Log("Pending Create Terminal");
  68. try
  69. {
  70. terminal = new Terminal("cmd.exe", w, h);
  71. }
  72. catch (Exception exception)
  73. {
  74. Log(exception.ToString());
  75. return;
  76. }
  77. Log("Terminal Created");
  78. e.Channel.DataReceived += (ss, ee) => terminal.OnInput(ee);
  79. e.Channel.CloseReceived += (ss, ee) => terminal.OnClose();
  80. terminal.DataReceived += (ss, ee) => e.Channel.SendData(ee);
  81. terminal.CloseReceived += (ss, ee) => e.Channel.SendClose(ee);
  82. terminal.Run();
  83. }
  84. };
  85. }
  86. };
  87. };
  88. _server.Start();
  89. var field = _server.GetType().GetField("_listenser", BindingFlags.Instance | BindingFlags.NonPublic);
  90. var listener = (TcpListener)field.GetValue(_server);
  91. _listenEndPoint = (IPEndPoint)listener.Server.LocalEndPoint;
  92. context.PostMapRequestHandler += delegate
  93. {
  94. WebSocketForwardModule.ForwardCurrentContext("terminal", ConfigurationManager.AppSettings["PassCode"], _listenEndPoint);
  95. };
  96. }
  97. public void Dispose()
  98. {
  99. _server?.Stop();
  100. }
  101. }
  102. }