Skip to content

Commit

Permalink
Add a stupid way to test a server
Browse files Browse the repository at this point in the history
  • Loading branch information
HMBSbige committed Jul 4, 2019
1 parent b88a4ac commit a00cd21
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 22 deletions.
2 changes: 2 additions & 0 deletions shadowsocks-csharp/Data/cn.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ Empty Response=空连
Error Percent=出错比例
Continuous=连错
Version=版本
Experimental=实验性功能
Test selected server=测试选定的服务器

# Global Log Form

Expand Down
2 changes: 2 additions & 0 deletions shadowsocks-csharp/Data/zh-tw.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ Empty Response=空連
Error Percent=出錯比例
Continuous=連錯
Version=版本
Experimental=實驗性功能
Test selected server=測試選定的伺服器

# Global Log Form

Expand Down
2 changes: 1 addition & 1 deletion shadowsocks-csharp/Model/ServerSpeedLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public long AvgUploadBytes

#region 延迟

public long AvgConnectTime => avgConnectTime;
public int AvgConnectTime => avgConnectTime;

public long AvgConnectTimeText
{
Expand Down
14 changes: 7 additions & 7 deletions shadowsocks-csharp/Proxy/HttpProxyRunner.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
using System;
using Shadowsocks.Controller;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Shadowsocks.Controller;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;

namespace Shadowsocks.Proxy
{
class HttpProxyRunner
public class HttpProxyRunner
{
private static readonly string UNIQUE_CONFIG_FILE;
private static readonly Job PRIVOXY_JOB;
Expand Down Expand Up @@ -126,7 +126,7 @@ private static bool IsChildProcess(Process process)
}
}

private static int GetFreePort()
public static int GetFreePort()
{
const int defaultPort = 60000;
try
Expand Down
38 changes: 24 additions & 14 deletions shadowsocks-csharp/Proxy/ProxyAuth.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System;
using Shadowsocks.Controller;
using Shadowsocks.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Shadowsocks.Controller;
using Shadowsocks.Model;

namespace Shadowsocks.Proxy
{
Expand Down Expand Up @@ -517,19 +517,29 @@ private bool HttpHandshakeRecv()

private void Connect()
{
Handler.GetCurrentServer getCurrentServer = delegate (int localPort, ServerSelectStrategy.FilterFunc filter, string targetURI, bool cfgRandom, bool usingRandom, bool forceRandom) { return _config.GetCurrentServer(localPort, filter, targetURI, cfgRandom, usingRandom, forceRandom); };
Handler.KeepCurrentServer keepCurrentServer = delegate (int localPort, string targetURI, string id) { _config.KeepCurrentServer(localPort, targetURI, id); };
Server GetCurrentServer(int localPort, ServerSelectStrategy.FilterFunc filter, string targetURI, bool cfgRandom, bool usingRandom, bool forceRandom)
=> _config.GetCurrentServer(localPort, filter, targetURI, cfgRandom, usingRandom, forceRandom);

void KeepCurrentServer(int localPort, string targetURI, string id)
{
_config.KeepCurrentServer(localPort, targetURI, id);
}

int local_port = ((IPEndPoint)_connection.LocalEndPoint).Port;
Handler handler = new Handler();

handler.getCurrentServer = getCurrentServer;
handler.keepCurrentServer = keepCurrentServer;
handler.connection = new ProxySocketTunLocal(_connection);
handler.connectionUDP = _connectionUDP;
handler.cfg.ReconnectTimesRemain = _config.reconnectTimes;
handler.cfg.Random = _config.random;
handler.cfg.ForceRandom = _config.random;
Handler handler = new Handler
{
getCurrentServer = GetCurrentServer,
keepCurrentServer = KeepCurrentServer,
connection = new ProxySocketTunLocal(_connection),
connectionUDP = _connectionUDP,
cfg =
{
ReconnectTimesRemain = _config.reconnectTimes,
Random = _config.random,
ForceRandom = _config.random
}
};

handler.setServerTransferTotal(_transfer);
if (_config.proxyEnable)
{
Expand Down
198 changes: 198 additions & 0 deletions shadowsocks-csharp/Util/SimpleSocksProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Shadowsocks.Util
{
public class ConnectionException : ApplicationException
{
public ConnectionException(string message) : base(message)
{ }
}
public static class SimpleSocksProxy
{
#region ErrorMessages
private static readonly string[] ErrorMessages = {
@"Operation completed successfully.",
@"General SOCKS server failure.",
@"connection not allowed by ruleset.",
@"Network unreachable.",
@"Host unreachable.",
@"Connection refused.",
@"TTL expired.",
@"Command not supported.",
@"Address type not supported.",
@"Unknown error."
};
#endregion

private static Socket ConnectToSocks5Proxy(string proxyAddress, ushort proxyPort,
string destAddress, ushort destPort,
string userName, string password)
{
if (userName == null)
{
userName = string.Empty;
}
if (password == null)
{
password = string.Empty;
}

var request = new byte[257];
var response = new byte[257];

if (IPAddress.TryParse(proxyAddress, out var proxyIp))
{
proxyIp = Dns.GetHostAddresses(proxyAddress)[0];
}

IPAddress.TryParse(destAddress, out var destIp);

var proxyEndPoint = new IPEndPoint(proxyIp, proxyPort);

// open a TCP connection to SOCKS server...
var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(proxyEndPoint);

ushort nIndex = 0;
request[nIndex++] = 0x05; // Version 5.
request[nIndex++] = 0x02; // 2 Authentication methods are in packet...
request[nIndex++] = 0x00; // NO AUTHENTICATION REQUIRED
request[nIndex++] = 0x02; // USERNAME/PASSWORD
// Send the authentication negotiation request...
s.Send(request, nIndex, SocketFlags.None);

// Receive 2 byte response...
var nGot = s.Receive(response, 2, SocketFlags.None);
if (nGot != 2)
throw new ConnectionException("Bad response received from proxy server.");

if (response[1] == 0xFF)
{ // No authentication method was accepted close the socket.
s.Close();
throw new ConnectionException("None of the authentication method was accepted by proxy server.");
}

byte[] rawBytes;

if (/*response[1]==0x02*/true)
{//Username/Password Authentication protocol
nIndex = 0;
request[nIndex++] = 0x05; // Version 5.

// add user name
request[nIndex++] = (byte)userName.Length;
rawBytes = Encoding.Default.GetBytes(userName);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;

// add password
request[nIndex++] = (byte)password.Length;
rawBytes = Encoding.Default.GetBytes(password);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;

// Send the Username/Password request
s.Send(request, nIndex, SocketFlags.None);
// Receive 2 byte response...
nGot = s.Receive(response, 2, SocketFlags.None);
if (nGot != 2)
throw new ConnectionException("Bad response received from proxy server.");
if (response[1] != 0x00)
throw new ConnectionException("Bad Username/Password.");
}
// This version only supports connect command.
// UDP and Bind are not supported.

// Send connect request now...
nIndex = 0;
request[nIndex++] = 0x05; // version 5.
request[nIndex++] = 0x01; // command = connect.
request[nIndex++] = 0x00; // Reserve = must be 0x00

if (destIp != null)
{
if (destIp.AddressFamily == AddressFamily.InterNetwork)
{
// Address is IPV4 format
request[nIndex++] = 0x01;
rawBytes = destIp.GetAddressBytes();
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
}
else if (destIp.AddressFamily == AddressFamily.InterNetworkV6)
{
// Address is IPV6 format
request[nIndex++] = 0x04;
rawBytes = destIp.GetAddressBytes();
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
}
}
else
{
// Address is full-qualified domain name.
request[nIndex++] = 0x03;
// length of address.
request[nIndex++] = Convert.ToByte(destAddress.Length);
rawBytes = Encoding.Default.GetBytes(destAddress);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
}

// using big-endian byte order
var portBytes = BitConverter.GetBytes(destPort);
Array.Reverse(portBytes);
foreach (var b in portBytes)
{
request[nIndex++] = b;
}

// send connect request.
s.Send(request, nIndex, SocketFlags.None);
// Get variable length response...
s.ReceiveTimeout = 3000;
s.Receive(response);
if (response[1] != 0x00)
{
throw new ConnectionException(ErrorMessages[response[1]]);
}
// Success Connected...
return s;
}

public static bool TestLocalSocks5(ushort port, string pass, string user)
{
const string strGet = "GET / HTTP/1.1\n\r\n";
var bytesReceived = new byte[1024];
Socket client = null;
try
{
client = ConnectToSocks5Proxy(
IPAddress.Loopback.ToString(), port,
@"www.google.com",
80, pass, user);
client.Send(Encoding.UTF8.GetBytes(strGet));
var bytes = client.Receive(bytesReceived, bytesReceived.Length, 0);
var page = Encoding.UTF8.GetString(bytesReceived, 0, bytes);
if (page.StartsWith(@"HTTP/1.1 200 OK"))
{
return true;
}

return false;
}
catch
{
return false;
}
finally
{
client?.Close();
client?.Dispose();
}
}
}
}
3 changes: 3 additions & 0 deletions shadowsocks-csharp/View/ServerLogWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@
<MenuItem x:Name="AutoSizeMenuItem" Click="AutoSizeMenuItem_OnClick"/>
<MenuItem x:Name="AlwaysTopMenuItem" IsChecked="{Binding Topmost,ElementName=Slw}" Click="AlwaysTopMenuItem_OnClick"/>
</MenuItem>
<MenuItem x:Name="TestMenuItem" Header="Experimental">
<MenuItem x:Name="TestSelectedMenuItem" Click="TestSelectedMenuItem_OnClick" />
</MenuItem>
</Menu>

<DataGrid x:Name="ServerDataGrid"
Expand Down
Loading

0 comments on commit a00cd21

Please sign in to comment.