Ejemplo n.º 1
0
        public static async Task <MinecraftHandshake> Read(Stream stream)
        {
            var handshake = new MinecraftHandshake();

            handshake.ProtocolVersion = await stream.ReadVarInt();

            handshake.ServerAddress = await stream.ReadVarString();

            handshake.Port = await stream.ReadUShort();

            handshake.NextState = (State)await stream.ReadVarInt();

            return(handshake);
        }
Ejemplo n.º 2
0
        private ProxyRule.ProxyEndpoint[] ResolveEndpoint(MinecraftHandshake handshake)
        {
            var endpoints = new List <ProxyRule.ProxyEndpoint>();

            foreach (ProxyRule rule in Config.Rules)
            {
                if (rule.DoesMatch(handshake.ServerAddressWithoutMagicString, handshake.ProtocolVersion))
                {
                    endpoints.AddRange(rule.Endpoints);
                }
            }

            return(endpoints.ToArray());
        }
Ejemplo n.º 3
0
        public async Task Listen(Stream client, ResolveToServerEndpoints resolveDelegate)
        {
            // Try and read Minecraft packet structure
            int packetLength = await client.ReadVarInt();

            // Read packet body
            byte[] buffer = new byte[packetLength];
            await client.ReadAsync(buffer, 0, packetLength);

            var packetStream = new MemoryStream(buffer);

            int packetId = await packetStream.ReadVarInt();

            if (packetId != 0)
            {
                // Not handshake packet
                throw new ProtocolException("Illegal packet ID for handshake");
            }

            // Read handshake packet
            var handshake = await MinecraftHandshake.Read(packetStream);

            HandshakeReceived?.Invoke(this, handshake);

            // Resolve to a server endpoint based on handshake
            ProxyRule.ProxyEndpoint[] endpoints = resolveDelegate(handshake);
            if (endpoints == null || endpoints.Length == 0)
            {
                await WriteDisconnectPacket(client, $"Proxy server has no server for this hostname.", "red");

                throw new NoServersMatchException(handshake);
            }

            // Try to connect to an endpoint
            NetworkStream tunnel = null;

            ProxyRule.ProxyEndpoint connectedEndpoint = null;
            foreach (var endpointObj in endpoints)
            {
                try
                {
                    // This will just grab the endpoint, or do a DNS lookup if needed
                    IPEndPoint endpoint = await endpointObj.GetEndpoint();

                    var tunnelClient = new TcpClient();
                    await tunnelClient.ConnectAsync(endpoint.Address, endpoint.Port);

                    tunnel = tunnelClient.GetStream();

                    connectedEndpoint = endpointObj;
                    Connected?.Invoke(this, endpointObj);
                    break;
                }
                catch (Exception e)
                {
                    EndpointFailed?.Invoke(this, endpointObj);
                }
            }

            if (tunnel == null || connectedEndpoint == null)
            {
                await WriteDisconnectPacket(client, $"Proxy server cannot connect to origin server.", "red");

                throw new Exception("No server endpoints are accessible.");
            }

            // Modify handshake before we resend it to appear as if we connected directly to the target server
            bool fmlMagicStringPresent = handshake.ServerAddress.EndsWith("\0FML\0");

            if (connectedEndpoint.DnsHostname == null)
            {
                handshake.ServerAddress = connectedEndpoint.Endpoint.Address.ToString();
            }
            else
            {
                handshake.ServerAddress = connectedEndpoint.DnsHostname;
            }

            // Reappend FML magic string
            if (fmlMagicStringPresent)
            {
                handshake.ServerAddress += "\0FML\0";
            }

            handshake.Port = (ushort)connectedEndpoint.Port;

            try
            {
                // Resend handshake packet
                var resendHandshakeStream = new MemoryStream();
                await resendHandshakeStream.WriteVarInt(0); // Packet ID 0 (handshake)

                await handshake.Write(resendHandshakeStream);

                byte[] resendHandshakeBytes = resendHandshakeStream.ToArray();

                await tunnel.WriteVarInt(resendHandshakeBytes.Length);                         // Packet length

                await tunnel.WriteAsync(resendHandshakeBytes, 0, resendHandshakeBytes.Length); // Packet body

                // Proxy traffic backwards and forwards
                await Task.WhenAny(client.CopyToAsync(tunnel), tunnel.CopyToAsync(client));

                // Close connection
                tunnel?.Close();
                client?.Close();
            }
            catch {}
        }
Ejemplo n.º 4
0
 public NoServersMatchException(MinecraftHandshake handshake) : base($"No servers for {handshake.ServerAddress}.")
 {
     Handshake = handshake;
 }