Reverse proxy to VNC server

1. Caddy version (caddy version):

2.1.1

2. How I run Caddy:

a. System environment:

Arch Linux 64 Bit

b. Command:

caddy run

c. My complete Caddyfile or JSON config:

{
    auto_https off
}

127.0.0.1:8888 {

    reverse_proxy * http://127.0.0.1:5900 {

        header_up Host {http.request.host}
        header_up X-Real-IP {http.request.remote}
        header_up X-Forwarded-For {http.request.remote}
        header_up X-Forwarded-Port {http.request.port}
        header_up X-Forwarded-Proto {http.request.scheme}

    }
}

3. The problem I’m having:

I’m trying to reverse proxy to a VNC server. The VNC server is on port 5900 and everything works fine when I try to connect to it. Now I expect that the exact same thing happens when I connect to :8888 but It is just stuck at CConn: Connected to host 127.0.0.1 port 8888 (I’m using TigerVNC for connecting by the way). When I stop the vncviewer process Caddy shows me this: http: TLS handshake error from 127.0.0.1:59892: EOF so I think it is stuck in the TLS handshake. But I disabled https, right?

4. Error messages and/or full log output:

I already posted it above… This is the full one.

2020/07/30 21:02:54.786	INFO	using adjacent Caddyfile
2020/07/30 21:02:54.787	INFO	admin	admin endpoint started	{"address": "tcp/localhost:2019", "enforce_origin": false, "origins": ["[::1]:2019", "127.0.0.1:2019", "localhost:2019"]}
2020/07/30 21:02:54.787	INFO	tls	cleaned up storage units
2020/07/30 23:02:54    [INFO][cache:0xc000538d20] Started certificate maintenance routine
2020/07/30 21:02:54.787	INFO	autosaved config	{"file": "/home/lennard/.config/caddy/autosave.json"}
2020/07/30 21:02:54.788	INFO	serving initial configuration
2020/07/30 23:03:03     http: TLS handshake error from 127.0.0.1:59892: EOF

5. What I already tried:

I first tried to do it without the header_up stuff. Didn’t work so I googled a bit. Added it but it still doesn’t work… And now I’m here :slight_smile:

Howdy @fahhlach,

Caddy v2’s reverse_proxy Caddyfile directive is a HTTP (Hyper-Text Transfer Protocol) proxy.

VNC uses RFB (Remote Frame Buffer) protocol. I don’t think RFB over HTTPS is a thing; having a quick google turns up SSH tunneling as the secure method of accessing VNC.

While Caddy might allow you to establish a connection to itself, it can’t talk RFB, so it can’t be the middleman between your VNC client and your VNC server.

For that you will need a TCP/UDP proxy. Matt Holt’s Project Conncept might interest you: https://github.com/mholt/conncept


P.S. All those header_up lines should be unnecessary for 99% of proxies, and half of them (the important ones) are already set by Caddy and are redundant anyway:

By default, Caddy passes thru incoming headers to the backend—including the Host header—without modifications, with two exceptions:

https://caddyserver.com/docs/caddyfile/directives/reverse_proxy

And doubly so because VNC doesn’t speak headers. Did you copy them in from a guide somewhere?

1 Like

Thanks for your answer! I just assumed that VNC uses websockets… Learned something new:)
Project Conncept looks promising but I’m 15 and can’t afford to sponsor @matt even though I’d like to because his work is awesome.
I thought I could use the automatic HTTPS feature from Caddy to secure the VNC servers but now I’ll probably have to use Nginx…

Edit: What I need is something like the net module from Caddy v1. Is there anything like this for v2?

1 Like

Project Conncept is effectively the replacement for the net plugin from v1, but it’s way more powerful.

Like @Whitestrake said I think you should instead look into SSH tunnelling here instead which is a more generalized solution for solving what you’re trying to do.

Also not so tech-savvy people should connect so SSH tunneling is probably too complicated from a user’s perspective.

Honestly I’d just recommend using TeamViewer if you’re looking for a solution for non-tech people. VNC isn’t the easiest thing to make user-friendly. But maybe I’m misunderstanding what you’re looking to do.

This feels a bit like an XY problem here:

I probably gave too little information. The desktop I want to remote desktop into is actually virtualized by QEMU. Thus I’m using the integrated VNC server via the -vnc command line parameter. Using TeamViewer, AnyDesk or other software would normally also be my way to go but in this case I want to use VNC because QEMU already uses it natively.

What operating system is the guest?

If it’s Windows, the gold standard is a HTTPS RD Gateway (which unfortunately you can’t put stock Caddy in front of, but you can use Conncept for). The second best option is a VPN and direct RDP to the guest. You won’t beat RDP for performance or quality; VNC is quite literally a simple network-accessible frame buffer, and it suffers all of the problems associated with that.

Even if they’re not connecting to a Windows guest, you might consider setting up a VPN anyway - run an OpenVPN or WireGuard server on your QEMU host, give your unsavvy users a neat little client certificate bundle to drop into their VPN client and it’s click-and-go. Then pre-configure their VNC client to point to the QEMU guest over the private network.