V2: How to 'transfer' the real ip?

1. My Caddy version (caddy version):

v2.0.0-rc.1 h1:DxUlg4kMisXwXVnWND7KEPl1f+vjFpIOzYpKpfmwyj8=

2. How I run Caddy:

Caddy is running in a docker container. It serves as a reverse proxy for my nextcloud instance that is running in an other docker container.

a. System environment:

Docker

Client:
 Version:           19.03.8-ce
 API version:       1.40
 Go version:        go1.14
 Git commit:        afacb8b7f0
 Built:             Tue Mar 17 23:37:06 2020
 OS/Arch:           linux/arm64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.8-ce
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.14
  Git commit:       afacb8b7f0
  Built:            Tue Mar 17 23:36:36 2020
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          v1.3.3.m
  GitCommit:        d76c121f76a5fc8a462dc64594aea72fe18e1178.m
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

b. Command:

/caddy/bin/caddy run --environ --watch --config /caddy/etc/Caddyfile

c. Service/unit/compose file:

version: "3.2"

services:
    srv:
        build:
            context: .
            dockerfile: Dockerfile

        container_name: caddy

        volumes:
            - etc:/caddy/etc
            - srv:/caddy/srv
        
        networks:
            - default

        ports:
            - 192.168.0.12:10443:443/tcp
            - 192.168.0.12:10080:80/tcp

        restart: 
            unless-stopped

volumes:
    etc:
    srv:

###
networks:
    default:
        external:
            name: web    
#

d. My complete Caddyfile or JSON config:

cloud.mydomain.com {
   encode gzip 

   # Service discovery via well-known
   redir /.well-known/carddav /remote.php/carddav 301
   redir /.well-known/caldav /remote.php/caldav 301

   reverse_proxy http://nextcloud-srv {
      header_down Strict-Transport-Security "max-age=15552000;"
      header_up X-Real-IP {remote_host}
      header_up X-Forwarded-For {remote_host}
   }

   log {
      output file         /caddy/srv/access.log
      format single_field /caddy/srv/common_log
   }

   tls contact@mydomain.com
}

3. The problem I’m having:

When I check the log file for nextcloud I see that the IP is the one for Caddy and not the client that is connecting to nextcloud through the reverse proxy.

Without the real IP I cann use the feature to block user depending on the estimated country of thier IP address.

How can I get the client’s IP ?

4. Error messages and/or full log output:

No error, just wrong IP in log file.

5. What I already tried:

I tried to set header_up for X-Real-IP and X-Forwarded-For.

6. Links to relevant resources:

N/A

I don’t think this is an issue with your Caddy config.

I think you need to configure Nextcloud to trust Caddy’s IP as a proxy. See Reverse proxy — Nextcloud latest Administration Manual latest documentation

I configured the trusted_proxies I still get caddy’s IP.

  array (
    0 => 'caddy',
    1 => '172.18.0.4',
  ),

I inspected the container for caddy and the IP is correct. Right now I connecting to my server through a port forwarding on my router. I do see in caddy’s log that the IP is the LAN IP for my router. This is fine. However it’s not the IP I see one nexcloud side. I also tried to connect using my smartphone: I see it’s Internet IP correctly but again nextcloud keeps showing Caddy’s IP.

At this point I think you’ll need to get help from the NextCloud forums. As far as I can tell, everything you’ve done in Caddy is correct.

Thank you. I’ll check on nextcloud side. If I find anything I’ll post it back here.

1 Like

After a closer look, this is incorrect - /caddy/srv/common_log isn’t a valid formatter, you should have format single_field common_log instead.

1 Like

I rewrote the log section

   log {
      output file /caddy/srv/access.log {
         roll_size 200MiB
         roll_keep 5
      }
   }

I found the problem. In fact everything was fine. The problem was apache that was not logging the correct info.

By default the Apache log looks like the following:

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

The apache documentation clearly indicate that in case of a reverse proxy %h will be the IP of the reverse proxy, not the client.

To fixed it I replaced %h with %{X-Forwarded-For}

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

I also made sure that the IP of my reverse proxy is trused (/etc/apache2/conf-enabled/remoteip.conf)

RemoteIPTrustedProxy 172.18.0.0/16

Here I’m using an IP range because I’m not using static IP for my docker container. It’s not a big problem for a home installation. The 172.18.0.0/16 subnet is dedicated to docker.

With the above changes I now have the correct IP in apache log file.

2 Likes

Thanks for following up with your solution! Very interesting.

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