Search code examples
virtual-machineqemuportforwarding

How can we forward a port to QEMU which has a server on the port already running?


I have a Python server running at port 28009:

python3 -m http.server 28009

Now, after I run the server I call QEMU to forward port 28009:

qemu-system-aarch64 -nographic -machine virt,gic-version=max -m 512M -cpu max -smp 4 \
-netdev user,id=vnet,hostfwd=tcp::28009-:28009 -device virtio-net-pci,netdev=vnet \
-drive file=ubuntu-image.img,if=none,id=drive0,cache=writeback -device virtio-blk,drive=drive0,bootindex=0 \
-drive file=flash0.img,format=raw,if=pflash -drive file=flash1.img,format=raw,if=pflash 

It produces an error saying:

qemu-system-aarch64: Could not set up host forwarding rule 'tcp::28009-:28009'

Similarly, if I run the above QEMU script first it boots alright. However, the Python server now throws an error:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.6/http/server.py", line 1211, in <module>
    test(HandlerClass=handler_class, port=args.port, bind=args.bind)
  File "/usr/lib/python3.6/http/server.py", line 1185, in test
    with ServerClass(server_address, HandlerClass) as httpd:
  File "/usr/lib/python3.6/socketserver.py", line 456, in __init__
    self.server_bind()
  File "/usr/lib/python3.6/http/server.py", line 136, in server_bind
    socketserver.TCPServer.server_bind(self)
  File "/usr/lib/python3.6/socketserver.py", line 470, in server_bind
    self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use

How can I have the server running and enable QEMU to access this server? I cannot use a TUN connection as I need to have localhost of the host machine talking to QEMU and vice versa.


Solution

  • The hostfwd option is for forwarding connections from the outside world to a server which is running on the guest. "hostfwd=tcp::HOSTPORT-:GUESTPORT" says "QEMU should listen on the host on port HOSTPORT; whenever a connection arrives there, it should forward it to the guest's port GUESTPORT (which hopefully has a server listening there)".

    You seem to be running a server on the host. You can't have more than one thing listening on a particular port on one machine, so either the python3 server program can listen on port 28009 and respond to connections there, or QEMU can listen on port 28009 to respond to connections there (forwarding them to the guest), but not both at once. Whichever is started second will complain that something's already using the port.

    If you want to run a server on the host and connect to it from the guest, you don't need any QEMU options at all. QEMU's 'usermode' networking will allow guest programs to make connections outwards to any IP address (including the wider internet but also directly to the host), so if you are trying to run a client on the guest and a server on the host that should just work. You can tell the guest client to connect either to the host's real IP address or you can use the special 'gateway' IP address 10.0.2.2 which is how the host machine appears on the fake network that the guest sees.