This commit is contained in:
Anonymous
2023-07-29 23:37:10 +05:30
parent c6c629437c
commit 85f5411b6e
158 changed files with 220479 additions and 4 deletions

View File

@@ -0,0 +1,491 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Server.Connection;
using Server.Helper;
namespace Server.ReverseProxy;
public class ReverseProxyClient
{
public enum ProxyType
{
Unknown,
SOCKS5,
HTTPS
}
public const int SOCKS5_DEFAULT_PORT = 3218;
public const byte SOCKS5_VERSION_NUMBER = 5;
public const byte SOCKS5_RESERVED = 0;
public const byte SOCKS5_AUTH_NUMBER_OF_AUTH_METHODS_SUPPORTED = 2;
public const byte SOCKS5_AUTH_METHOD_NO_AUTHENTICATION_REQUIRED = 0;
public const byte SOCKS5_AUTH_METHOD_GSSAPI = 1;
public const byte SOCKS5_AUTH_METHOD_USERNAME_PASSWORD = 2;
public const byte SOCKS5_AUTH_METHOD_IANA_ASSIGNED_RANGE_BEGIN = 3;
public const byte SOCKS5_AUTH_METHOD_IANA_ASSIGNED_RANGE_END = 127;
public const byte SOCKS5_AUTH_METHOD_RESERVED_RANGE_BEGIN = 128;
public const byte SOCKS5_AUTH_METHOD_RESERVED_RANGE_END = 254;
public const byte SOCKS5_AUTH_METHOD_REPLY_NO_ACCEPTABLE_METHODS = byte.MaxValue;
public const byte SOCKS5_CMD_REPLY_SUCCEEDED = 0;
public const byte SOCKS5_CMD_REPLY_GENERAL_SOCKS_SERVER_FAILURE = 1;
public const byte SOCKS5_CMD_REPLY_CONNECTION_NOT_ALLOWED_BY_RULESET = 2;
public const byte SOCKS5_CMD_REPLY_NETWORK_UNREACHABLE = 3;
public const byte SOCKS5_CMD_REPLY_HOST_UNREACHABLE = 4;
public const byte SOCKS5_CMD_REPLY_CONNECTION_REFUSED = 5;
public const byte SOCKS5_CMD_REPLY_TTL_EXPIRED = 6;
public const byte SOCKS5_CMD_REPLY_COMMAND_NOT_SUPPORTED = 7;
public const byte SOCKS5_CMD_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 8;
public const byte SOCKS5_ADDRTYPE_IPV4 = 1;
public const byte SOCKS5_ADDRTYPE_DOMAIN_NAME = 3;
public const byte SOCKS5_ADDRTYPE_IPV6 = 4;
public const int BUFFER_SIZE = 8192;
private bool _receivedConnResponse;
private MemoryStream _handshakeStream;
private byte[] _buffer;
private bool _isBindCommand;
private bool _isUdpCommand;
private bool _isConnectCommand;
private bool _isIpType;
private bool _isIPv6NameType;
private bool _isDomainNameType;
private bool _disconnectIsSend;
private ReverseProxyServer Server;
public Socket Handle { get; private set; }
public string UserIP
{
get
{
try
{
return ((IPEndPoint)Handle.RemoteEndPoint).Address.ToString();
}
catch
{
}
return "Unknown";
}
}
public string ClientIP => Client.Ip;
public string TypeStr
{
get
{
if (Type == ProxyType.SOCKS5)
{
return "SOCK5";
}
if (Type == ProxyType.HTTPS)
{
return "HTTPS";
}
return "Unknown";
}
}
public string UserCountry => Utils.GetCountryName(UserIP);
public string ClientCountry => Utils.GetCountryName(ClientIP);
public string ReceivedStr => Utils.GetSizeString(LengthReceived);
public string SendStr => Utils.GetSizeString(LengthSent);
public string TargetStr => $"{TargetServer} : {TargetPort}";
public Clients Client { get; private set; }
public long PacketsReceived { get; private set; }
public long PacketsSended { get; private set; }
public long LengthReceived { get; private set; }
public long LengthSent { get; private set; }
public int ConnectionId => Handle.Handle.ToInt32();
public string TargetServer { get; private set; }
public ushort TargetPort { get; private set; }
public bool IsConnected { get; private set; }
public ProxyType Type { get; private set; }
public string HostName { get; private set; }
public bool ProxySuccessful { get; private set; }
public ReverseProxyClient(Clients client, Socket socket, ReverseProxyServer server)
{
Handle = socket;
Client = client;
_handshakeStream = new MemoryStream();
_buffer = new byte[8192];
IsConnected = true;
TargetServer = "";
Type = ProxyType.Unknown;
Server = server;
try
{
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
}
catch
{
Disconnect();
}
}
private void AsyncReceive(IAsyncResult ar)
{
try
{
int num = Handle.EndReceive(ar);
if (num <= 0)
{
Disconnect();
return;
}
if (num > 5000 || _handshakeStream.Length + num > 5000)
{
Disconnect();
return;
}
LengthReceived += num;
_handshakeStream.Write(_buffer, 0, num);
}
catch
{
Disconnect();
return;
}
byte[] array = _handshakeStream.ToArray();
switch (PacketsReceived)
{
case 0L:
{
if (array.Length < 3)
{
break;
}
string @string = Encoding.ASCII.GetString(array);
if (array[0] == 5)
{
Type = ProxyType.SOCKS5;
}
if (!@string.StartsWith("CONNECT") || !@string.Contains(":"))
{
break;
}
Type = ProxyType.HTTPS;
using StreamReader streamReader = new StreamReader(new MemoryStream(array));
string text = streamReader.ReadLine();
if (text == null)
{
break;
}
string[] array2 = text.Split(new string[1] { " " }, StringSplitOptions.RemoveEmptyEntries);
if (array2.Length != 0)
{
try
{
string text2 = array2[1];
TargetServer = text2.Split(':')[0];
TargetPort = ushort.Parse(text2.Split(':')[1]);
_isConnectCommand = true;
_isDomainNameType = true;
Client.SendProxyCommand(new ReverseProxyConnect
{
ConnectionId = ConnectionId,
Target = TargetServer,
Port = TargetPort
}, ReverseProxyCommands.CONNECT);
Server.CallonConnectionEstablished(this);
return;
}
catch
{
Disconnect();
}
}
goto IL_01cf;
}
case 1L:
{
int num2 = 6;
if (array.Length < num2)
{
break;
}
if (!CheckProxyVersion(array))
{
return;
}
_isConnectCommand = array[1] == 1;
_isBindCommand = array[1] == 2;
_isUdpCommand = array[1] == 3;
_isIpType = array[3] == 1;
_isDomainNameType = array[3] == 3;
_isIPv6NameType = array[3] == 4;
Array.Reverse(array, array.Length - 2, 2);
TargetPort = BitConverter.ToUInt16(array, array.Length - 2);
if (_isConnectCommand)
{
if (_isIpType)
{
TargetServer = array[4] + "." + array[5] + "." + array[6] + "." + array[7];
}
else if (_isDomainNameType)
{
int num3 = array[4];
if (num2 + num3 < array.Length)
{
TargetServer = Encoding.ASCII.GetString(array, 5, num3);
}
}
if (TargetServer.Length > 0)
{
Client.SendProxyCommand(new ReverseProxyConnect
{
ConnectionId = ConnectionId,
Target = TargetServer,
Port = TargetPort
}, ReverseProxyCommands.CONNECT);
}
Server.CallonUpdateConnection(this);
}
else
{
SendFailToClient();
}
return;
}
IL_01cf:
if (CheckProxyVersion(array))
{
SendSuccessToClient();
PacketsReceived++;
_handshakeStream.SetLength(0L);
Server.CallonConnectionEstablished(this);
}
break;
}
try
{
Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
}
catch
{
Disconnect();
}
}
public void Disconnect()
{
if (!_disconnectIsSend)
{
_disconnectIsSend = true;
Client.SendProxyCommand(new ReverseProxyDisconnect
{
ConnectionId = ConnectionId
}, ReverseProxyCommands.DISCONNECT);
}
try
{
Handle.Close();
}
catch
{
}
IsConnected = false;
Server.CallonUpdateConnection(this);
}
public void SendToClient(byte[] payload)
{
lock (Handle)
{
try
{
LengthSent += payload.Length;
Handle.Send(payload);
}
catch
{
Disconnect();
}
}
Server.CallonUpdateConnection(this);
}
private void SendFailToClient()
{
if (Type == ProxyType.HTTPS)
{
Disconnect();
}
if (Type == ProxyType.SOCKS5)
{
SendToClient(new byte[2] { 5, 255 });
Disconnect();
}
}
private void SendSuccessToClient()
{
if (Type == ProxyType.SOCKS5)
{
SendToClient(new byte[2] { 5, 0 });
}
}
private bool CheckProxyVersion(byte[] payload)
{
if (Type == ProxyType.HTTPS)
{
return true;
}
if (payload.Length != 0 && payload[0] != 5)
{
SendFailToClient();
Disconnect();
return false;
}
return true;
}
public void HandleCommandResponse(ReverseProxyConnectResponse response)
{
if (_receivedConnResponse)
{
return;
}
_receivedConnResponse = true;
if (response.IsConnected)
{
HostName = response.HostName;
if (Type == ProxyType.HTTPS)
{
SendToClient(Encoding.ASCII.GetBytes("HTTP/1.0 200 Connection established\r\n\r\n"));
}
else if (Type == ProxyType.SOCKS5)
{
try
{
List<byte> list = new List<byte>();
list.Add(5);
list.Add(0);
list.Add(0);
list.Add(1);
list.AddRange(response.LocalAddress);
list.Add((byte)Math.Floor((decimal)response.LocalPort / 256m));
list.Add((byte)(response.LocalPort % 256));
SendToClient(list.ToArray());
}
catch
{
SendToClient(new byte[10] { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 });
}
}
_handshakeStream.Close();
ProxySuccessful = true;
try
{
Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceiveProxy, null);
}
catch
{
Disconnect();
}
}
else if (Type == ProxyType.HTTPS)
{
Disconnect();
}
else if (Type == ProxyType.SOCKS5)
{
SendToClient(new byte[10] { 5, 5, 0, 1, 0, 0, 0, 0, 0, 0 });
}
Server.CallonUpdateConnection(this);
}
private void AsyncReceiveProxy(IAsyncResult ar)
{
try
{
int num = Handle.EndReceive(ar);
if (num <= 0)
{
Disconnect();
return;
}
LengthReceived += num;
ReverseProxyData reverseProxyData = new ReverseProxyData
{
ConnectionId = ConnectionId
};
reverseProxyData.Data = new byte[num];
Array.Copy(_buffer, reverseProxyData.Data, num);
Client.SendProxyCommand(reverseProxyData, ReverseProxyCommands.DATA);
LengthSent += num;
PacketsSended++;
}
catch
{
Disconnect();
return;
}
PacketsReceived++;
Server.CallonUpdateConnection(this);
try
{
Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceiveProxy, null);
}
catch
{
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Server.ReverseProxy;
public class ReverseProxyCommand
{
public int ConnectionId { get; set; }
}

View File

@@ -0,0 +1,10 @@
namespace Server.ReverseProxy;
public enum ReverseProxyCommands
{
CONNECT,
CONNECTRESPONSE,
DATA,
DISCONNECT,
INIT
}

View File

@@ -0,0 +1,8 @@
namespace Server.ReverseProxy;
public class ReverseProxyConnect : ReverseProxyCommand
{
public string Target { get; set; }
public int Port { get; set; }
}

View File

@@ -0,0 +1,14 @@
namespace Server.ReverseProxy;
public class ReverseProxyConnectResponse : ReverseProxyCommand
{
public bool IsConnected { get; set; }
public byte[] LocalAddress { get; set; }
public int LocalPort { get; set; }
public int RemotePort { get; set; }
public string HostName { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Server.ReverseProxy;
public class ReverseProxyData : ReverseProxyCommand
{
public byte[] Data { get; set; }
}

View File

@@ -0,0 +1,5 @@
namespace Server.ReverseProxy;
public class ReverseProxyDisconnect : ReverseProxyCommand
{
}

View File

@@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using Server.Connection;
namespace Server.ReverseProxy;
public class ReverseProxyServer
{
public delegate void ConnectionEstablishedCallback(ReverseProxyClient proxyClient);
public delegate void UpdateConnectionCallback(ReverseProxyClient proxyClient);
public readonly List<ReverseProxyClient> _clients = new List<ReverseProxyClient>();
private Socket _socket;
public Clients Clients { get; private set; }
private string UserIP
{
get
{
try
{
return ((IPEndPoint)_socket.RemoteEndPoint).Address.ToString();
}
catch
{
}
return "Unknown";
}
}
public ReverseProxyClient[] ProxyClients
{
get
{
lock (_clients)
{
return _clients.ToArray();
}
}
}
public ReverseProxyClient[] OpenConnections
{
get
{
lock (_clients)
{
List<ReverseProxyClient> list = new List<ReverseProxyClient>();
for (int i = 0; i < _clients.Count; i++)
{
if (_clients[i].ProxySuccessful)
{
list.Add(_clients[i]);
}
}
return list.ToArray();
}
}
}
public event ConnectionEstablishedCallback OnConnectionEstablished;
public event UpdateConnectionCallback OnUpdateConnection;
public void StartServer(Clients clients, ushort port)
{
Stop();
Clients = clients;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Parse("0.0.0.0"), port));
_socket.Listen(100);
_socket.BeginAccept(AsyncAccept, null);
}
private void AsyncAccept(IAsyncResult ar)
{
try
{
lock (_clients)
{
_clients.Add(new ReverseProxyClient(Clients, _socket.EndAccept(ar), this));
}
}
catch
{
}
try
{
_socket.BeginAccept(AsyncAccept, null);
}
catch
{
}
}
public void Stop()
{
if (_socket != null)
{
_socket.Close();
_socket = null;
}
lock (_clients)
{
foreach (ReverseProxyClient item in new List<ReverseProxyClient>(_clients))
{
item.Disconnect();
}
_clients.Clear();
}
}
public ReverseProxyClient GetClientByConnectionId(int connectionId)
{
lock (_clients)
{
return _clients.FirstOrDefault((ReverseProxyClient t) => t.ConnectionId == connectionId);
}
}
internal void CallonConnectionEstablished(ReverseProxyClient proxyClient)
{
try
{
if (this.OnConnectionEstablished != null)
{
this.OnConnectionEstablished(proxyClient);
}
}
catch
{
}
}
internal void CallonUpdateConnection(ReverseProxyClient proxyClient)
{
try
{
if (!proxyClient.IsConnected)
{
lock (_clients)
{
for (int i = 0; i < _clients.Count; i++)
{
if (_clients[i].ConnectionId == proxyClient.ConnectionId)
{
_clients.RemoveAt(i);
break;
}
}
}
}
}
catch
{
}
try
{
if (this.OnUpdateConnection != null)
{
this.OnUpdateConnection(proxyClient);
}
}
catch
{
}
}
public void KillConnection(int index)
{
try
{
OpenConnections[index]?.Disconnect();
}
catch
{
}
}
}