Accessing ONVIF cameras via reverse proxy

1. Caddy version (caddy version):

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

Caddy is run as a service using JSON API on Ubunto 20.04

a. System environment:

systemd

b. Command:

It’s automatically started at boot up time

c. Service/unit/compose file:

n/a

d. My complete Caddyfile or JSON config:

I am just posting the relevant information here as it’s too big for the forums to handle:

            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "rewrite",
                          "strip_path_prefix": "/trendnet"
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "headers": {
                            "request": {
                              "set": {
                                "Access-Control-Allow-Credentials": [
                                  "true"
                                ],
                                "Access-Control-Allow-Headers": [
                                  "Cache-Control,Content-Type"
                                ],
                                "Access-Control-Allow-Origin": [
                                  "*"
                                ],
                                "X-Forwarded-Proto": [
                                  "{http.request.scheme}"
                                ],
                                "X-Real-Ip": [
                                  "{http.request.remote.host}"
                                ]
                              }
                            }
                          },
                          "upstreams": [
                            {
                              "dial": "192.168.0.37:80"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "path": [
                    "/trendnet/*"
                  ]
                }
              ]
            },

3. The problem I’m having:

Ok, so we are working with 3 types of ONVIF cameras. The above configuration works for two of the cameras (Hikvision and Trendnet) but fails for the Axis camera. If you are unfamiliar with ONVIF cameras, one of the calls into the camera is GetServices. This returns a number of services that the camera can do, with the associated address (XADDR). We modify the address so that it can use the reverse proxy. So, this http://192.168.0.37/onvif/device_service will now look like this: http://localhost/trendnet/onvif/device_service. As I mentioned, this works for Hikvision and Trendnet cameras. What we have surmised, is that we know the Axis has stricter security than the other camera manufacturers, and we THINK it’s comparing the URL we are using to what it gave us and responding back with an “unauthorized” message. If we don’t use the reverse proxy and just straight IP, then we never see this error message.

My question then is there a way of rewriting the URL that the camera sees, to look like what it’s expecting?

This:
http://localhost/trendnet/onvif/device_service

Back to this:
http://192.168.0.37/onvif/device_service

We already use this:

"handle": [
                        {
                          "handler": "rewrite",
                          "strip_path_prefix": "/trendnet"
                        }
                      ]

But, it’s not sufficient. :frowning:

Any advice is welcomed. Thanks.

You can use reverse_proxy > headers > request > set to set the Host header to the IP address, I guess. (Should be the equivalent of header_up in the Caddyfile)

You may also use the {http.reverse_proxy.upstream.host} placeholder to grab the IP address of the configured upstream instead of hardcoding it.

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.