mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
- Created specific namespaces and folders for each app brick - Added proxy support using Starksoft's Biko Library - App bricks: Main, ChatBots, Crypto, Protocol, Proxy - Each class is now in its own file (Aes streams, chatbots) - Used "Bridge" design pattern for Crypto, Protocol, Proxy - Added back support for Minecraft 1.4.6 to 1.6.4 (MCC 1.6.2) - Need to fully re-test everything and fix bugs - To Fix : Server pinging is slow on SpigotMC - To Do : Add Minecraft 1.2.5 (MCC 1.3) and maybe 1.3 to 1.4.5
230 lines
11 KiB
C#
230 lines
11 KiB
C#
/*
|
|
* Authors: Benton Stark
|
|
*
|
|
* Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
using System;
|
|
using System.Text;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.IO;
|
|
|
|
namespace Starksoft.Net.Proxy
|
|
{
|
|
/// <summary>
|
|
/// Socks4a connection proxy class. This class implements the Socks4a standard proxy protocol
|
|
/// which is an extension of the Socks4 protocol
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// In Socks version 4A if the client cannot resolve the destination host's domain name
|
|
/// to find its IP address the server will attempt to resolve it.
|
|
/// </remarks>
|
|
public class Socks4aProxyClient : Socks4ProxyClient
|
|
{
|
|
private const string PROXY_NAME = "SOCKS4a";
|
|
|
|
/// <summary>
|
|
/// Default constructor.
|
|
/// </summary>
|
|
public Socks4aProxyClient()
|
|
: base()
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Creates a Socks4 proxy client object using the supplied TcpClient object connection.
|
|
/// </summary>
|
|
/// <param name="tcpClient">An open TcpClient object with an established connection.</param>
|
|
public Socks4aProxyClient(TcpClient tcpClient)
|
|
: base(tcpClient)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Create a Socks4a proxy client object. The default proxy port 1080 is used.
|
|
/// </summary>
|
|
/// <param name="proxyHost">Host name or IP address of the proxy server.</param>
|
|
/// <param name="proxyUserId">Proxy user identification information for an IDENTD server.</param>
|
|
public Socks4aProxyClient(string proxyHost, string proxyUserId)
|
|
: base(proxyHost, proxyUserId)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Create a Socks4a proxy client object.
|
|
/// </summary>
|
|
/// <param name="proxyHost">Host name or IP address of the proxy server.</param>
|
|
/// <param name="proxyPort">Port used to connect to proxy server.</param>
|
|
/// <param name="proxyUserId">Proxy user identification information.</param>
|
|
public Socks4aProxyClient(string proxyHost, int proxyPort, string proxyUserId)
|
|
: base(proxyHost, proxyPort, proxyUserId)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Create a Socks4 proxy client object. The default proxy port 1080 is used.
|
|
/// </summary>
|
|
/// <param name="proxyHost">Host name or IP address of the proxy server.</param>
|
|
public Socks4aProxyClient(string proxyHost) : base(proxyHost)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Create a Socks4a proxy client object.
|
|
/// </summary>
|
|
/// <param name="proxyHost">Host name or IP address of the proxy server.</param>
|
|
/// <param name="proxyPort">Port used to connect to proxy server.</param>
|
|
public Socks4aProxyClient(string proxyHost, int proxyPort)
|
|
: base(proxyHost, proxyPort)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Gets String representing the name of the proxy.
|
|
/// </summary>
|
|
/// <remarks>This property will always return the value 'SOCKS4a'</remarks>
|
|
public override string ProxyName
|
|
{
|
|
get { return PROXY_NAME; }
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Sends a command to the proxy server.
|
|
/// </summary>
|
|
/// <param name="proxy">Proxy server data stream.</param>
|
|
/// <param name="command">Proxy byte command to execute.</param>
|
|
/// <param name="destinationHost">Destination host name or IP address.</param>
|
|
/// <param name="destinationPort">Destination port number</param>
|
|
/// <param name="userId">IDENTD user ID value.</param>
|
|
/// <remarks>
|
|
/// This method override the SendCommand message in the Sock4ProxyClient object. The override adds support for the
|
|
/// Socks4a extensions which allow the proxy client to optionally command the proxy server to resolve the
|
|
/// destination host IP address.
|
|
/// </remarks>
|
|
internal override void SendCommand(NetworkStream proxy, byte command, string destinationHost, int destinationPort, string userId)
|
|
{
|
|
// PROXY SERVER REQUEST
|
|
//Please read SOCKS4.protocol first for an description of the version 4
|
|
//protocol. This extension is intended to allow the use of SOCKS on hosts
|
|
//which are not capable of resolving all domain names.
|
|
//
|
|
//In version 4, the client sends the following packet to the SOCKS server
|
|
//to request a CONNECT or a BIND operation:
|
|
//
|
|
// +----+----+----+----+----+----+----+----+----+----+....+----+
|
|
// | VN | CD | DSTPORT | DSTIP | USERID |NULL|
|
|
// +----+----+----+----+----+----+----+----+----+----+....+----+
|
|
// # of bytes: 1 1 2 4 variable 1
|
|
//
|
|
//VN is the SOCKS protocol version number and should be 4. CD is the
|
|
//SOCKS command code and should be 1 for CONNECT or 2 for BIND. NULL
|
|
//is a byte of all zero bits.
|
|
//
|
|
//For version 4A, if the client cannot resolve the destination host's
|
|
//domain name to find its IP address, it should set the first three bytes
|
|
//of DSTIP to NULL and the last byte to a non-zero value. (This corresponds
|
|
//to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The
|
|
//Internet Assigned Numbers Authority -- such an address is inadmissible
|
|
//as a destination IP address and thus should never occur if the client
|
|
//can resolve the domain name.) Following the NULL byte terminating
|
|
//USERID, the client must sends the destination domain name and termiantes
|
|
//it with another NULL byte. This is used for both CONNECT and BIND requests.
|
|
//
|
|
//A server using protocol 4A must check the DSTIP in the request packet.
|
|
//If it represent address 0.0.0.x with nonzero x, the server must read
|
|
//in the domain name that the client sends in the packet. The server
|
|
//should resolve the domain name and make connection to the destination
|
|
//host if it can.
|
|
//
|
|
//SOCKSified sockd may pass domain names that it cannot resolve to
|
|
//the next-hop SOCKS server.
|
|
|
|
// userId needs to be a zero length string so that the GetBytes method
|
|
// works properly
|
|
if (userId == null)
|
|
userId = "";
|
|
|
|
byte[] destIp = {0,0,0,1}; // build the invalid ip address as specified in the 4a protocol
|
|
byte[] destPort = GetDestinationPortBytes(destinationPort);
|
|
byte[] userIdBytes = ASCIIEncoding.ASCII.GetBytes(userId);
|
|
byte[] hostBytes = ASCIIEncoding.ASCII.GetBytes(destinationHost);
|
|
byte[] request = new byte[10 + userIdBytes.Length + hostBytes.Length];
|
|
|
|
// set the bits on the request byte array
|
|
request[0] = SOCKS4_VERSION_NUMBER;
|
|
request[1] = command;
|
|
destPort.CopyTo(request, 2);
|
|
destIp.CopyTo(request, 4);
|
|
userIdBytes.CopyTo(request, 8); // copy the userid to the request byte array
|
|
request[8 + userIdBytes.Length] = 0x00; // null (byte with all zeros) terminator for userId
|
|
hostBytes.CopyTo(request, 9 + userIdBytes.Length); // copy the host name to the request byte array
|
|
request[9 + userIdBytes.Length + hostBytes.Length] = 0x00; // null (byte with all zeros) terminator for userId
|
|
|
|
// send the connect request
|
|
proxy.Write(request, 0, request.Length);
|
|
|
|
// wait for the proxy server to send a response
|
|
base.WaitForData(proxy);
|
|
|
|
// PROXY SERVER RESPONSE
|
|
// The SOCKS server checks to see whether such a request should be granted
|
|
// based on any combination of source IP address, destination IP address,
|
|
// destination port number, the userid, and information it may obtain by
|
|
// consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
|
|
// server makes a connection to the specified port of the destination host.
|
|
// A reply packet is sent to the client when this connection is established,
|
|
// or when the request is rejected or the operation fails.
|
|
//
|
|
// +----+----+----+----+----+----+----+----+
|
|
// | VN | CD | DSTPORT | DSTIP |
|
|
// +----+----+----+----+----+----+----+----+
|
|
// # of bytes: 1 1 2 4
|
|
//
|
|
// VN is the version of the reply code and should be 0. CD is the result
|
|
// code with one of the following values:
|
|
//
|
|
// 90: request granted
|
|
// 91: request rejected or failed
|
|
// 92: request rejected becuase SOCKS server cannot connect to
|
|
// identd on the client
|
|
// 93: request rejected because the client program and identd
|
|
// report different user-ids
|
|
//
|
|
// The remaining fields are ignored.
|
|
//
|
|
// The SOCKS server closes its connection immediately after notifying
|
|
// the client of a failed or rejected request. For a successful request,
|
|
// the SOCKS server gets ready to relay traffic on both directions. This
|
|
// enables the client to do I/O on its connection as if it were directly
|
|
// connected to the application server.
|
|
|
|
// create an 8 byte response array
|
|
byte[] response = new byte[8];
|
|
|
|
// read the resonse from the network stream
|
|
proxy.Read(response, 0, 8);
|
|
|
|
// evaluate the reply code for an error condition
|
|
if (response[1] != SOCKS4_CMD_REPLY_REQUEST_GRANTED)
|
|
HandleProxyCommandError(response, destinationHost, destinationPort);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|