SystemRage / py-kms

KMS Server Emulator written in Python
The Unlicense
2.07k stars 634 forks source link

IPv6 and parsing errors #86

Closed oe688 closed 4 years ago

oe688 commented 4 years ago

I have IPv6 and parsing errors.

Due to security issues I have disabled ipv6;

root# grep ipv6 /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="nomodeset ipv6.disable=1"

This is how I download and setup py-kms;

root# addgroup --gid 8004 kms
root# adduser --uid 8004 --gid 8004 --disabled-password kms
root# su - kms
kms$ git clone https://github.com/SystemRage/py-kms.git
kms$ screen -S kms

Now I try to run pykms_Server.py;

kms$ ./py-kms/py-kms/pykms_Server.py -s :: 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '::'. Exiting...

kms$ ./py-kms/py-kms/pykms_Server.py -s 0.0.0.0 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '0.0.0.0'. Exiting...

kms$ ./py-kms/py-kms/pykms_Server.py :: 6881 -s
Connection failed ':::6881': [Errno 97] Address family not supported by protocol. Exiting...

kms$ ./py-kms/py-kms/pykms_Server.py 0.0.0.0 6881 -s
Connection failed '0.0.0.0:6881': [Errno 97] Address family not supported by protocol. Exiting...

Ok... let's look at the code...

kms$ vi ./py-kms/py-kms/pykms_Server.py
kms$ cd py-kms; git diff; cd
diff --git a/py-kms/pykms_Server.py b/py-kms/pykms_Server.py
index 73afc94..1253568 100755
--- a/py-kms/pykms_Server.py
+++ b/py-kms/pykms_Server.py
@@ -37,7 +37,7 @@ class KeyServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
         allow_reuse_address = True

         def __init__(self, server_address, RequestHandlerClass):
-                self.address_family = socket.AF_INET6 # This call make sure the server creates an IPv6 socket and NOT an IPv4 by default
+                # self.address_family = socket.AF_INET6 # This call make sure the server creates an IPv6 socket and NOT an IPv4 by default
                 socketserver.TCPServer.__init__(self, server_address, RequestHandlerClass)
                 self.__shutdown_request = False
                 self.r_service, self.w_service = socket.socketpair()

Now let's try again;

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py -s :: 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '::'. Exiting...

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py -s 0.0.0.0 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '0.0.0.0'. Exiting...

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py :: 6881 -s
Connection failed ':::6881': [Errno -9] Address family for hostname not supported. Exiting...

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py 0.0.0.0 6881 -s

YES! Let's check;

[detached from 6095.kms]
kms$ ss -pltuna | grep 6881
tcp    LISTEN  0       5                     0.0.0.0:6881         0.0.0.0:*      users:(("python3",pid=6138,fd=4))                                              

All seems to work fine now...

So two problems here; 1) the parsing; the -s :: 6881 should have worked 2) The handling of IPv4 / IPv6 logic seems to need some love

My very crude suggestion for IPv4 / IPv6 logic;

        def __init__(self, server_address, RequestHandlerClass):
            if ':' in server_address:
                self.address_family = socket.AF_INET6 

Thanks for the great program!

simonmicro commented 4 years ago

Yeah, we had a ton of issues with ipv6 - maybe a switch like you proposed would be helpful. I'll look into an additional command line parameter.

oe688 commented 4 years ago

I currently can't test IPv6 but my guess is that the "if" test I proposed covers all IPv4 and IPv6 cases transparently and works like users would expect.

SystemRage commented 4 years ago
kms@pola:~$ ./py-kms/py-kms/pykms_Server.py -s :: 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '::'. Exiting...

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py -s 0.0.0.0 6881
optional py-kms server argument `-s`: expected zero arguments, unrecognized: '0.0.0.0'. Exiting...

Behavior is as expected, you have to put your positional arguments (ipaddress, port) first and then other flags. You can ignore them, but you can't put them wherever you want.

kms@pola:~$ ./py-kms/py-kms/pykms_Server.py :: 6881 -s
Connection failed ':::6881': [Errno -9] Address family for hostname not supported. Exiting...

This works for me, so i don't know.

kms$ ./py-kms/py-kms/pykms_Server.py 0.0.0.0 6881 -s
Connection failed '0.0.0.0:6881': [Errno 97] Address family not supported by protocol. Exiting...

This not works, and your crude suggestion could be a solution.

oe688 commented 4 years ago

Behavior is as expected, you have to put your positional arguments (ipaddress, port) first and then other flags. You can ignore them, but you can't put them wherever you want.

Ah, ok. Thanks for clearing that up.

This works for me, so i don't know.

That's probably because you have ipv6 enabled, I have the ipv6 kernel module disabled (see my initial post).

This not works, and your crude suggestion could be a solution.

I think it is, but I can't currently test it, otherwise I would make a pull request.

simonmicro commented 4 years ago

I'll look into an additional command line parameter.

So i guess that is overkill :grin: .

I was worried that someone could try to enter IPv4:PORT and this would trigger ipv6. But this is only a theoretical concern as the parser should check for that...

oe688 commented 4 years ago

I'll look into an additional command line parameter.

So i guess that is overkill grin .

yep :)

I was worried that someone could try to enter IPv4:PORT and this would trigger ipv6. But this is only a theoretical concern as the parser should check for that...

If this is an issue, then here is even a more robust test, an IPv6 address always has 2 or more colons, so the code would be:

        def __init__(self, server_address, RequestHandlerClass):
            if server_address.count(':') >= 2:
                self.address_family = socket.AF_INET6 
oe688 commented 4 years ago

Tested. Works! Nice clean solution.

Thanks.