Browse Source

修复 RFC5389 测试,添加代理用户名密码支持,及 API 调整

Student Main 5 years ago
parent
commit
8fa04d0f22

+ 3 - 5
NatTypeTester/ViewModels/MainWindowViewModel.cs

@@ -195,10 +195,8 @@ namespace NatTypeTester.ViewModels
                             ProxyUser, ProxyPassword
                             );
 
-                        using var client = new StunClient3489(server.Hostname, proxy, server.Port,
-                                NetUtils.ParseEndpoint(LocalEnd));
-
-
+                        using var client = new StunClient3489(server.Hostname, server.Port,
+                                NetUtils.ParseEndpoint(LocalEnd), proxy);
 
                         client.NatTypeChanged.ObserveOn(RxApp.MainThreadScheduler)
                                 .Subscribe(t => ClassicNatType = $@"{t}");
@@ -234,7 +232,7 @@ namespace NatTypeTester.ViewModels
                             ProxyUser, ProxyPassword
                             );
 
-                        using var client = new StunClient5389UDP(server.Hostname, proxy, server.Port, NetUtils.ParseEndpoint(LocalAddress));
+                        using var client = new StunClient5389UDP(server.Hostname, server.Port, NetUtils.ParseEndpoint(LocalAddress), proxy);
 
 
 

+ 1 - 1
STUN/Client/StunClient3489.cs

@@ -49,7 +49,7 @@ namespace STUN.Client
 
         protected IUdpProxy Proxy;
 
-        public StunClient3489(string server, IUdpProxy proxy = null, ushort port = 3478, IPEndPoint local = null, IDnsQuery dnsQuery = null)
+        public StunClient3489(string server, ushort port = 3478, IPEndPoint local = null, IUdpProxy proxy = null, IDnsQuery dnsQuery = null)
         {
             Proxy = proxy ?? new NoneUdpProxy(local, null);
 

+ 4 - 3
STUN/Client/StunClient5389UDP.cs

@@ -33,14 +33,15 @@ namespace STUN.Client
 
         #endregion
 
-        public StunClient5389UDP(string server, IUdpProxy proxy, ushort port = 3478, IPEndPoint local = null, IDnsQuery dnsQuery = null)
-        : base(server, proxy, port, local, dnsQuery)
+        public StunClient5389UDP(string server, ushort port = 3478, IPEndPoint local = null, IUdpProxy proxy = null, IDnsQuery dnsQuery = null)
+        : base(server, port, local, proxy, dnsQuery)
         {
             Timeout = TimeSpan.FromSeconds(3);
         }
 
         public async Task<StunResult5389> QueryAsync()
         {
+            await Proxy.ConnectAsync();
             var result = new StunResult5389();
             _bindingSubj.OnNext(result.BindingTestResult);
             _mappingBehaviorSubj.OnNext(result.MappingBehavior);
@@ -92,6 +93,7 @@ namespace STUN.Client
             finally
             {
                 _mappingBehaviorSubj.OnNext(result.MappingBehavior);
+                await Proxy.DisconnectAsync();
             }
         }
 
@@ -104,7 +106,6 @@ namespace STUN.Client
         private async Task<StunResult5389> BindingTestBaseAsync(IPEndPoint remote, bool notifyChanged)
         {
             BindingTestResult res;
-
             var test = new StunMessage5389 { StunMessageType = StunMessageType.BindingRequest };
             var (response1, _, local1) = await TestAsync(test, remote, remote);
             var mappedAddress1 = AttributeExtensions.GetXorMappedAddressAttribute(response1);

+ 15 - 18
STUN/Proxy/Socks5UdpProxy.cs

@@ -24,19 +24,22 @@ namespace STUN.Proxy
             set => UdpClient.Client.ReceiveTimeout = Convert.ToInt32(value.TotalMilliseconds);
         }
 
-        public IPEndPoint LocalEndPoint { get; private set; }
+        public IPEndPoint LocalEndPoint { get => (IPEndPoint)UdpClient.Client.LocalEndPoint; }
 
         UdpClient UdpClient;
 
         string user;
-        string passwd;
+        string password;
         public Socks5UdpProxy(IPEndPoint local, IPEndPoint proxy)
         {
-            LocalEndPoint = local;
             UdpClient = local == null ? new UdpClient() : new UdpClient(local);
             socksTcpEndPoint = proxy;
         }
-
+        public Socks5UdpProxy(IPEndPoint local, IPEndPoint proxy, string user, string password) : this(local, proxy)
+        {
+            this.user = user;
+            this.password = password;
+        }
         public async Task ConnectAsync()
         {
             byte[] buf = new byte[1024];
@@ -45,7 +48,7 @@ namespace STUN.Proxy
             try
             {
                 var s = assoc.GetStream();
-                bool requestPasswordAuth = user != null;
+                bool requestPasswordAuth = !string.IsNullOrEmpty(user);
 
                 #region Handshake
                 // we have no gssapi support
@@ -71,7 +74,7 @@ namespace STUN.Proxy
                         break;
                     case 2:
                         byte[] ubyte = Encoding.UTF8.GetBytes(user);
-                        byte[] pbyte = Encoding.UTF8.GetBytes(passwd);
+                        byte[] pbyte = Encoding.UTF8.GetBytes(password);
                         buf[0] = 1;
                         buf[1] = (byte)ubyte.Length;
                         Array.Copy(ubyte, 0, buf, 2, ubyte.Length);
@@ -97,18 +100,11 @@ namespace STUN.Proxy
                 buf[2] = 0;
 
                 int addrLen;
-                int port;
-                byte[] abyte = IPAddress.Any.GetAddressBytes();
+                byte[] abyte = GetEndPointByte(new IPEndPoint(IPAddress.Any, 0));
                 addrLen = abyte.Length;
-                buf[3] = (byte)(abyte.Length == 4 ? 1 : 4);
-                Array.Copy(abyte, 0, buf, 4, addrLen);
-                port = 0;
-
-                buf[addrLen + 4] = (byte)(port / 256);
-                buf[addrLen + 5] = (byte)(port % 256);
-
+                Array.Copy(abyte, 0, buf, 3, addrLen);
                 // 5 cmd(3=udpassoc) 0 atyp(1=v4 3=dns 4=v5) addr port
-                s.Write(buf, 0, addrLen + 6);
+                s.Write(buf, 0, addrLen + 3);
                 #endregion
 
                 #region UDP Assoc Response
@@ -147,7 +143,8 @@ namespace STUN.Proxy
         public async Task<(byte[], IPEndPoint, IPAddress)> RecieveAsync(byte[] bytes, IPEndPoint remote, EndPoint receive)
         {
             TcpState state = assoc.GetState();
-            if (state != TcpState.Established) throw new Exception();
+            if (state != TcpState.Established)
+                throw new InvalidOperationException("No UDP association, maybe already disconnected or not connected");
 
             byte[] remoteBytes = GetEndPointByte(remote);
             byte[] proxyBytes = new byte[bytes.Length + remoteBytes.Length + 3];
@@ -211,7 +208,7 @@ namespace STUN.Proxy
             ret[ipbyte.Length + 2] = (byte)(ep.Port % 256);
             return ret;
         }
-    
+
         public void Dispose()
         {
             UdpClient?.Dispose();

+ 1 - 1
STUN/Utils/NetUtils.cs

@@ -46,7 +46,7 @@ namespace STUN.Utils
         public static async Task<StunResult5389> NatBehaviorDiscovery(string server, ushort port, IPEndPoint local)
         {
             // proxy is not supported yet
-            using var client = new StunClient5389UDP(server, null, port, local);
+            using var client = new StunClient5389UDP(server, port, local);
             return await client.QueryAsync();
         }