lima icon indicating copy to clipboard operation
lima copied to clipboard

Revamp port forwarding to support UDP

Open balajiv113 opened this issue 1 year ago • 5 comments

Fixes #366 Discussion - #2402

Revamps port forwarding to use existing GRPC communication.

Advantages

  • No SSH daemon (See Notes below)
  • No Subprocess for SSH
  • Faster (See performance below)
  • Ease of support for newer protocol (We do support UDP as well with this implementation)

Todo

  • [x] GRPC based tunnels
  • [x] TCP support
  • [x] UDP support
  • [x] Config to enable / disable this new port forwarding model
  • [x] Testing on MacOS
  • [ ] Testing on Linux
  • [ ] Testing on Windows

Performance GRPC TCP - ~3.80 Gbits/sec GRPC TCP Reverse - ~4.77 Gbits/sec SSH TCP - ~3.38 Gbits/sec SSH TCP Reverse - ~3.08 Gbits/sec

Notes

  • We will support only TCP and UDP via this approach. Unix and unixgram support socket to be added later as a separate PR
  • We support forwarding from host (Listen) -> guest (Dial). We don't support reverse forwarding host (Dial) -> guest (Listen) as of this PR. But can be extended and support it in a separate PR

balajiv113 avatar Jun 10 '24 08:06 balajiv113

Converting to draft as it needs some more changes related to handling of ports on host side

balajiv113 avatar Jun 13 '24 05:06 balajiv113

The failing tests run fine locally. Looks like some UDP port is enabled in these github runner and that is causing issue

Edit: Found the issue, it was related to mutex. I missed to unlock mutex properly on error cases

balajiv113 avatar Jun 27 '24 09:06 balajiv113

@lima-vm/maintainers Do we need to back this feature on with a config in lima yaml ??

Just thinking because we are looking at this as a drop-in replacement. If we went with config we need to mark this experimental and later bring it to stable / default. Also it will pollute the yaml as well

One another idea is to back this with a ENV / start option

balajiv113 avatar Jun 27 '24 13:06 balajiv113

ENV

👍

AkihiroSuda avatar Jun 27 '24 13:06 AkihiroSuda

Added a env and updated docs as well for this feature.

@lima-vm/maintainers We are good to review this PR.

I have done decent amount of testing in macOS and a very basic test in linux. For performance tried with iperf3 for both tcp and udp. Need some help to test in windows (Not sure if we even support port forwarding here, i think wsl takes care of it)

balajiv113 avatar Jun 27 '24 15:06 balajiv113

@lima-vm/maintainers Can we merge this?

AkihiroSuda avatar Jul 23 '24 05:07 AkihiroSuda

@jandubois @afbjorklund Do you need more testers?

moenodedev avatar Aug 08 '24 19:08 moenodedev

I'm sorry, I won't have time to test/review this until September. 😞

jandubois avatar Aug 09 '24 00:08 jandubois

@balajiv113 I have been testing UDP port forwarding with some Docker Compose applications, and I may have found an issue.

After I first run docker compose up, any UDP ports that I choose to expose are reachable, as expected. However, I find that after I restart the application, those ports are not reachable anymore. This does not happen with TCP port forwarding. TCP ports that I expose in the container(s) are reachable even after restarting. The only way I was able to make the UDP ports for my Compose apps reachable again was to restart the Lima VM. However, the problem reappears when I restart the Compose app.

To test, I built Lima from your most recent commit in this PR at the time of writing this comment. I created a VM using the Docker template with the following command: limactl create --vm-type vz template://docker --name=default. Below is the docker-compose.yml for a simple Docker Compose application that demonstrates the issue:

services:
  iperf3-server:
    image: networkstatic/iperf3
    command: -s
    ports:
      - "5201:5201/udp"
      - "5201:5201/tcp"

To verify whether or not the iperf3-server container is listening on TCP port 5201 and UDP port 5201, I used sudo lsof -i TCP:5201 and sudo lsof -i UDP:5201, respectively. If it is listening on a port, the command should have output. If there is no output, then that means the service is not listening on the port. When I run the Compose app for the first time, I get output from both commands. After restarting the app, I only get output from the lsof command for the TCP port.

Although I was primarily using Docker Compose in my tests, it seems to affect Docker containers in general. If I start a container with a certain UDP port forwarded, then stop it, then that UDP port is not able to be exposed in subsequently created containers, until the Lima VM is restarted.

Would be curious to see if you or anyone else can reproduce this.

I am testing this on macOS Sonoma 14.5 on an Intel Mac. I am also able to test on a Sonoma machine with Apple silicon.

suhailskhan avatar Aug 11 '24 08:08 suhailskhan

@suhailskhan Thanks for trying it out.

Yes it is indeed a issue. It happens due to conn cache on guest side. On closing of listener its not cleared properly Will fix and let you know

balajiv113 avatar Aug 12 '24 06:08 balajiv113

@suhailskhan Fixed it. It should work now

balajiv113 avatar Aug 12 '24 11:08 balajiv113

@balajiv113 Pulled, rebuilt, and tested. Works indeed!

suhailskhan avatar Aug 12 '24 22:08 suhailskhan

Lint is failing

AkihiroSuda avatar Aug 30 '24 05:08 AkihiroSuda

@AkihiroSuda Done. All Green

balajiv113 avatar Sep 02 '24 06:09 balajiv113