GithubSshHandler.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using FastGithub.DomainResolve;
  2. using Microsoft.AspNetCore.Connections;
  3. using System;
  4. using System.IO;
  5. using System.IO.Pipelines;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. namespace FastGithub.ReverseProxy
  11. {
  12. /// <summary>
  13. /// github的ssl处理者
  14. /// </summary>
  15. sealed class GithubSshHandler : ConnectionHandler
  16. {
  17. private const int SSH_PORT = 22;
  18. private const string GITHUB_COM = "github.com";
  19. private readonly IDomainResolver domainResolver;
  20. /// <summary>
  21. /// github的ssl处理者
  22. /// </summary>
  23. /// <param name="domainResolver"></param>
  24. public GithubSshHandler(IDomainResolver domainResolver)
  25. {
  26. this.domainResolver = domainResolver;
  27. }
  28. /// <summary>
  29. /// ssh连接后
  30. /// </summary>
  31. /// <param name="connection"></param>
  32. /// <returns></returns>
  33. public override async Task OnConnectedAsync(ConnectionContext connection)
  34. {
  35. var address = await this.domainResolver.ResolveAsync(GITHUB_COM, CancellationToken.None);
  36. var socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  37. await socket.ConnectAsync(new IPEndPoint(address, SSH_PORT));
  38. using var upStream = new NetworkStream(socket, ownsSocket: true);
  39. var downStream = new SshStream(connection.Transport);
  40. var task1 = upStream.CopyToAsync(downStream);
  41. var task2 = downStream.CopyToAsync(upStream);
  42. await Task.WhenAny(task1, task2);
  43. }
  44. /// <summary>
  45. /// 表示Ssh的流
  46. /// </summary>
  47. private class SshStream : Stream
  48. {
  49. private readonly Stream readStream;
  50. private readonly Stream wirteStream;
  51. /// <summary>
  52. /// Ssh的流
  53. /// </summary>
  54. /// <param name="transport"></param>
  55. public SshStream(IDuplexPipe transport)
  56. {
  57. this.readStream = transport.Input.AsStream();
  58. this.wirteStream = transport.Output.AsStream();
  59. }
  60. public override bool CanRead => true;
  61. public override bool CanSeek => false;
  62. public override bool CanWrite => true;
  63. public override long Length => throw new NotSupportedException();
  64. public override long Position
  65. {
  66. get => throw new NotSupportedException();
  67. set => throw new NotSupportedException();
  68. }
  69. public override void Flush()
  70. {
  71. this.wirteStream.Flush();
  72. }
  73. public override Task FlushAsync(CancellationToken cancellationToken)
  74. {
  75. return this.wirteStream.FlushAsync(cancellationToken);
  76. }
  77. public override long Seek(long offset, SeekOrigin origin)
  78. {
  79. throw new NotSupportedException();
  80. }
  81. public override void SetLength(long value)
  82. {
  83. throw new NotSupportedException();
  84. }
  85. public override int Read(byte[] buffer, int offset, int count)
  86. {
  87. return this.readStream.Read(buffer, offset, count);
  88. }
  89. public override void Write(byte[] buffer, int offset, int count)
  90. {
  91. this.wirteStream.Write(buffer, offset, count);
  92. }
  93. public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
  94. {
  95. return this.readStream.ReadAsync(buffer, cancellationToken);
  96. }
  97. public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  98. {
  99. return this.readStream.ReadAsync(buffer, offset, count, cancellationToken);
  100. }
  101. public override void Write(ReadOnlySpan<byte> buffer)
  102. {
  103. this.wirteStream.Write(buffer);
  104. }
  105. public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  106. {
  107. return this.wirteStream.WriteAsync(buffer, offset, count, cancellationToken);
  108. }
  109. public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
  110. {
  111. await this.wirteStream.WriteAsync(buffer, cancellationToken);
  112. }
  113. }
  114. }
  115. }