Need help with proxying a port request from outside network (think port forwarding on a router)

I feel kind of silly asking this, but I’d like to keep port forwarding on my router to just 80 and 443 and let Caddy handle everything else, however, I can’t figure out how to proxy a port request instead of a subdomain or subdirectory. I have an app that requires a remote access port be specified and will not allow for the use of a subdirectory.

For example, I’d like to set up something like this, but haven’t been able to in any of these cases

https://www.mydomain.com:5541 {
  proxy / 192.168.1.100:554
}
mydomain.com:5541 {
  proxy / 192.168.1.100:554
}
:5541 {
  proxy / 192.168.1.100:554
}

Hi @TehNiemer, we can get Caddy working the way you’re asking, but sometimes figuring out how all the ports need to be lined up through NAT can be annoying to figure out. Just a few questions to help get an idea of the situation currently:

What external ports have you forwarded from your router, and where (what IP and port) did you forward them to?

What domain and port do you want to configure your app to communicate with? Does the app in question need valid HTTPS or does it only talk HTTP?

Did you record any error messages or output from Caddy when you tried to start it with those Caddyfiles?

@Whitestrake I have 80 and 443 forwarded to Caddy (192.168.1.20:81, 192.168.1.20:444)

The app supposedly supports both HTTP and HTTPS, I would prefer HTTPS as these are cameras and I’d like the extra security.

I’d like to use a subdomain, something like cameras.mydomain.com, each camera needs two ports accessible, 80 and 554. The app can only use port numbers to access the cameras, but I can define the port for each camera, so my port forwarding would be something like this

app 8001 → 80 cam1
app 5541 → 554 cam1
app 8002 → 80 cam2
app 5442 → 554 cam2
etc…

I did not record any errors from Caddy, but I could re-create this pretty easily and see if anything pops up.

@Whitestrake I checked logs and they are empty.

So ports 80 and 443 on the WAN interface of your router are forwarded to ports 81 and 444 on your Caddy host, respectively?

In that case, you will need to run Caddy so that it expects traffic on those internal ports instead of the default HTTP and HTTPS ports. By default it will try to bind to 80 and 443.

You can use the flags -http-port and -https-port to do this. With a Caddyfile like:

cameras.mydomain.com {
  proxy / https://[CAMERA_IP]:554 {
    insecure_skip_verify
  }
}

Run Caddy with the flags -conf /path/to/Caddyfile -http-port 81 -https-port 444 and let us know how that goes.

@Whitestrake, Caddy is functioning correctly for me with my other sub-domains and sub-directories. So 80 and 443 are forwarding correctly to Caddy.

When I do this

cameras.mydomain.com {
  proxy / https://[CAMERA_IP]:80 {
    insecure_skip_verify
  }
}

I get the following errors

[12/Jan/2019:17:47:34 +0000] "GET / HTTP/2.0" 502 16
[12/Jan/2019:17:47:41 +0000] "GET /favicon.ico HTTP/2.0" 502 16

Also, I need access to two ports on the camera from one subdomain, without using a subdirectory.

OK, so this works

cameras.mydomain.com {
  proxy / [CAMERA_IP]:80 {
    insecure_skip_verify
  }
}

But, I still need to access port 554 on the same sub-domain without using a sub-directory. And ideally I’d be able to access both ports (80 and 554) of all my cameras with this one sub-domain.

That’s because you’ve put https://[CAMERA_IP]:80. I would put money down that port 80 is HTTP, not HTTPS. Use the HTTPS port instead, or remove the https:// part and the insecure_skip_verify (it’s not necessary if you’re not connecting to a non-validated HTTPS).

You can use just about any other method to differentiate with another site that servers the second camera. You can have one on HTTP and one on HTTPS, you can have one on one port and one on another, you could have one on one subdomain and one on a different subdomain, etc.

But you’ll want to set up two site blocks in the Caddyfile, one for each camera.

@Whitestrake well, the real issue is how to serve the second port on the same IP without using a second subdomain or subdirectory. Hopefully this screenshot will help clarify my intent. The remote web port number and remote rtsp port number are what I need to serve, but I cannot put anything other than a number in those fields.

If that’s connecting from outside your network, it’ll be connecting to those ports on your router. You can port forward 8001 and 5541 from your router to the hosts inside the network that you want to communicate with.

The web port you can forward to Caddy, but Caddy can’t handle the RTSP connection unless you use the net server type.

Well I have no idea how to use the net plugin, so I guess I’ll have to fall back to forwarding the ports on my router. Bummer.

It is fairly simple, but it would simply be another point in the network between your app and your cameras, and I don’t see how it would help.

It really looks like your app is only configured to talk to one camera at a time; there’s really no way to have multiple hosts (your cameras) answering on the same scheme/port/domain/path (same URL). Is there no central NVR system to handle your cameras together? I would have assumed that would be the correct target to forward to.

The app, Tinycam, can communicate with all the cameras at once. Each camera gets it’s own configuration in the app and a different port to communicate on. So, the screenshot above would be for camera 1, then camera 2 would be the same, except the remote ports would be 8002 and 5542, so on and so forth.

I’m not a networking guy, and I barely got caddy to work in Docker with http-reauth, so I’m afraid that if I try to get it setup with net I’m going to break it.

Ahh, OK, so you can add each camera individually using that screen? This is doable, then (but I’m still not sure Caddy is the right tool for the job).

You’re going to need to do a lot of port forwarding. Two ports on your router for every camera, basically. One for web, one for RTSP.

Lets assume the cameras are all listening on the same ports on your internal network, 80 and 554.

You should forward ports like so:

Router WAN      -> Host LAN

[external]:8001 -> [camera1]:80
[external]:5541 -> [camera1]:554

[external]:8002 -> [camera2]:80
[external]:5542 -> [camera2]:554

[external]:8003 -> [camera3]:80
[external]:5543 -> [camera3]:554

etc...

I’d be remiss not to mention that unless your cameras are individually secured, this could be a big security risk.

Hah, it’s about as simple as port forwarding. You tell Caddy what port to listen on, and then which host/port to send the traffic. Worst you can do is listen on the wrong port or forward to the wrong location.

OK, so no way to avoid port forwarding on the router?

TL;DR: Pretty much zero chance.

This is the implication of NAT (Network Address Translation). Your internet service provider assigns customers, in the vast majority of circumstances, only one IP address. But only having one IP address can be a problem; how do the multiple devices in your home communicate on the internet if they can’t all have IP addresses?

Enter NAT. You have the public internet on one side (the WAN side) of your router, and a private internet on the other (the LAN side). When your device on the LAN talks to a server on the internet, all the traffic goes through your router, and the server is effectively receiving requests and replying directly to your router, which is translating that back to your device.

It’s fairly easy for NAT to handle multiple devices trying to talk to servers on the internet - the outgoing connections can be given specific ports for this purpose automatically so the router can keep track of which reply traffic is for which device.

But how does an external client (your Tinycam app when you’re away from home) communicate with specific hosts on your private internet / LAN? Well… it can’t. You’ve only got one IP address, and it’s for your router.

But you do have multiple ports on that router. Enter port forwarding - you can manually configure your router to tell it that when someone on WAN tries to connect to a specific port, all that traffic should go to one specific host.

You’ve done this with Caddy. And you’ve come to this thread hoping that you can have Caddy handle the distribution of connections after that point. But there are two major issues with this approach. Firstly, Caddy’s HTTP server only has four metrics by which to decide how to handle an incoming request:

  1. Scheme (i.e. HTTP or HTTPS)
  2. Hostname (e.g. example.com)
  3. Port (e.g. :80, :443)
  4. Path (e.g. /subfolder)

Since you can’t change the hostname or the path, you’re left with port or scheme. Caddy can’t multiplex HTTP and HTTPS on the same port, so you’re left with only one meaningful differentiator, of which you have two options, for a maximum of two cameras (one configured on HTTP/80, one configured on HTTPS/443). Caddy could proxy to a different camera on each.

That doesn’t solve your RTSP problem, though. Caddy’s HTTP server doesn’t speak RTSP, and while Caddy’s net server does, the net server naturally can’t use any of the above differentiators for an incoming connection, other than port. Which leaves us with only two potential connections - really, only one camera, because each camera uses two ports (HTTP and RTSP).

The router is the choke point for ports, because it’s the gateway to the internet at large, and because port forwarding has to be one port mapped to one LAN destination. You can open up more ports, and point them at Caddy’s net server, but why do that? Caddy’s net server acts effectively as a port forwarder anyway, the cool part about it is that it can leverage the tls directive. You might as well just have your router do it.

1 Like

Thanks for the detailed explanation, that helps me understand how this all works a little better.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.