-1

We have an old multiplayer game (no source code) which crashes any time someone sends the server unexpected packets, and many of the players use telnet to do it with ease. I'm using iptables, and I want to filter out packets (and drop the connection) that the game server will not recognize. I want to do the following to the game server's port:

Pseudocode

if (PSH flag && Payload.Length > 0 bytes && Payload.Length < 6 bytes)
{
    // reject data, and drop client

}
else if (PSH flag && Payload.Length > 2)
{
    if (First3BytesOfPayload Not in [7f:ef:09, dc:0b:09, 08:00:09])
    {
        // reject data, and drop client

    }
}

This is not a foolproof solution, but it should work good enough for the few people we have. How can I accomplish this with iptables, if at all?

Thank you for your time.

  • The trouble with your first rule is that it will drop a lot of genuine data. And there is no guarantee the PSH flag will ever be set. – user207421 Jan 06 '21 at 05:12
  • I ran the server, and multiple clients. All the PSH packets fit a signature. I can already reject malformed packets that are not properly flagged. – user2616079 Jan 06 '21 at 10:50
  • TCP is a byte stream. You shouldn't be expecting individual packets to contain specific bytes. If the client sends X bytes, TCP is free to send 1+ packets containing any combination of 1..X bytes, as long as they are sequential. For what you are asking, you really should write a proxy instead and place it in front of the server. Have the clients connect to the proxy, and then let the proxy read the bytes and validate them before forwarding them to the game server. – Remy Lebeau Jan 12 '21 at 00:58
  • @RemyLebeau I'd upvote your comment but I'm forbidden. All this makes perfect sense. and I'd definitely do that if I knew what I was doing. I've run wireshark many times, and none of the packets have been fragmented (yet). – user2616079 Jan 14 '21 at 02:10

1 Answers1

0

I figured it out. I did it with the rules below (not all the rules), and it works wonderfully. I suppose I could have used the iptables length option, but I didn't need it. Anyone deciding to do this should make it specific to a port, and understand their program's tcp messaging protocol first, or else you may get locked out.

iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0x7fef09" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0xdc0b09" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0x080009" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -j DROP