How can Caddy pass user's IP and how to open additional port?

1. Caddy version (caddy version):

v2.0.0

2. How I run Caddy:

Default way after installing by official installation manual for Ubuntu:

a. System environment:

Ubuntu 18.04.4 (4.15.0-99-generic)

b. Command:

paste command here

c. Service/unit/compose file:

paste full file contents here

d. My complete Caddyfile or JSON config:

Config is based on instructions I’ve found here

{
    # email to use on Let's Encrypt
    email [removed for privacy]

    # Uncomment for debug
    #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
    #debug
}

# Add gzip compression to requests
(webconf) {
  encode gzip
}

# Add forward headers to requests
(theheaders) {
    header_up X-Forwarded-Ssl on
    header_up Host {host}
    header_up X-Real-IP {remote}
    header_up X-Forwarded-For {remote}
    header_up X-Forwarded-Port {server_port}
    header_up X-Forwarded-Proto {scheme}
    header_up X-Url-Scheme {scheme}
    header_up X-Forwarded-Host {host}
}

build.joycraft-games.com {
    reverse_proxy http://172.15.1.3:8080 {
      import theheaders
    }
    import webconf
}

svn.joycraft-games.com {
    reverse_proxy http://172.15.1.4 {
     import theheaders
    }
    import webconf
}

doc.joycraft-games.com {
    reverse_proxy http://172.15.1.8:80 {
     import theheaders
    }
    import webconf
}

ftp.joycraft-games.com {
    reverse_proxy http://172.15.1.5 {
     import theheaders
    }
    import webconf
}

box.joycraft-games.com {
    reverse_proxy http://172.15.1.2:80 {
     import theheaders
     header_down Strict-Transport-Security "max-age=15552000;"
     header_down Referrer-Policy "strict-origin-when-cross-origin"
     header_down X-XSS-Protection "1; mode=block"
     header_down X-Content-Type-Options "nosniff"
     header_down X-Frame-Options "SAMEORIGIN"
    }
    import webconf
}

3. The problem I’m having:

With config I’ve pasted above everything works great except I need some other functions for proxy and I have no idea how to make that because I’m a complete reverse-proxy noob.

So first problem is with IP address of connected user. I’m using bruteforce protection on my “box” domain (NextCloud, 172.15.1.2) and when someone failed to enter credentials for 3 times in a row everyone is blocked for 30 seconds because Box thinks what all users are on same IP (172.15.1.1) - where Caddy is. Is there a way to pass user’s IP instead of proxy IP to box?
I have header_up X-Real-IP {remote} in confing which I think should do the job. But looks it does nothing or is used in wrong way.

My second one is that I have to open and additional port to build domain, so it have to listen to 80, 443 and, let’s say, 99995 at same time for build.joycraft-games.com and then redirect 80 and 443 to 172.15.1.3:8080 (as it is in current config) and also from build.joycraft-games.com:99995 to 172.15.1.3:99995. I’ve found this on reverse proxy quick start guide but even if it looks like that can help me I have to idea how to add that to my Caddyfile.

4. Error messages and/or full log output:

5. What I already tried:

Looking through community forums and official docs but it looks I’m not that good at that.

6. Links to relevant resources:

You don’t need to add X-Forwarded-For and X-Forwarded-Proto, those are done for you already in Caddy v2.

Also, header_up X-Forwarded-Port {server_port} is incorrect, {server_port} isn’t a valid placeholder. See the list of shorthands supported in the Caddyfile:

There are plenty more placeholders available, see here (and also each other module may add their own placeholders):

I think your issue with NextCloud is that you haven’t configured which hosts are trusted proxies:

https://docs.nextcloud.com/server/15/admin_manual/configuration_server/reverse_proxy_configuration.html

2 Likes

Just set up sites for the places you want to redirect from, and use the redir directive to send them where you want them to go.

build.joycraft-games.com:80, build.joycraft-games.com:443 {
  redir 172.15.1.3:8080
}

build.joycraft-games.com:99995 {
  redir 172.15.1.3:99995
}
1 Like

My problem with NextCloud is aslo what I’m using easy to install but no so easy to configure snap package.
I’ve already tried to do

# snap run nextcloud.occ config:system:set trusted_proxies 1 --value=172.15.1.1
# snap restart nextcloud

And I thought that’s enough. Thank you, I’ll look more into this and learn placeholders.

Hm. I didn’t thought about splitting that into two records for same domain. Will try that at evening, thank you.

So this:

will still work same way as my current:

just without imports, right?

Oh no, they’re not the same at all.

My example is a redirect. Your config is a reverse proxy.

A redirect is having Caddy say to the client: “go away, and connect to <this address> instead”.

A reverse proxy is when Caddy connects to <this address> on behalf of the client, grabs the response, and returns it to the client. You can imagine it like pretending to be <this address> as far as the client knows.

1 Like

Ok, if I understand that right (English isn’t my main language so sometimes I’m lost in translation) , redirect is just like port forwarding on a router so with redirect there won’t be https with auto ssl. Then can I use it this way to have both reverse proxy and redir?


build.joycraft-games.com:99995 {
  redir 172.15.1.3:99995
}

build.joycraft-games.com {
    reverse_proxy http://172.15.1.3:8080
}

No, sorry, this isn’t it. Port forwarding is something else entirely, and happens at a lower level (network layer, between networking devices, e.g. your router and your PC). Redirecting, or proxying, happens as part of communication at a much higher level (application layer, between two applications, e.g. a browser and Caddy).

A redirect from Caddy’s perspective:

example.com {
  redir 172.15.1.3:99995
}

Client: “Hi, I’d like the web page for example.com, please!”
Caddy: “I don’t have it! Go to 172.15.1.3:99995 and ask them instead!”
Client: “OK, bye!”


A reverse proxy from Caddy’s perspective:

example.com {
  reverse_proxy 172.15.1.3:99995
}

Client: “Hi, I’d like the web page for example.com, please!”
Caddy: “Hi! Just a sec!”

Caddy: connects to 172.15.1.3:99995
Caddy: “Hi, I’d like the web page for example.com, please!”
172.15.1.3:99995: “Sure, here you go!”
172.15.1.3:99995: transmits a web page
Caddy: “Thank you, bye!”

Caddy: returns to client
Caddy: “Sure, here you go!”
Caddy: transmits a web page
Client: “Thank you, bye!”


So, basically, these are two completely different kinds of responses. Your latest example will work if you want to use the first kind of response for requests to port 99995, and the second kind of response for requests to the website on standard HTTP(S) ports.

3 Likes

My first problem was solved pretty easy - I just had to remove incorrect placeholders from my config so now I have “theheaders” snippet like this:

    (theheaders) {
    header_up X-Forwarded-Ssl on
    header_up Host {host}
    header_up X-Real-IP {remote}
    header_up X-Forwarded-Port {remote_port}
    header_up X-Url-Scheme {scheme}
    header_up X-Forwarded-Host {host}

    }

My cofing for NextCloud was correct from the beginning and

was enough to get reverse proxy IP as trusted. And now NextCloud is getting correct user IP as it should be.

Second one is more complicated for me. I’ve tried this:

But with no success. Actually I have a Jenkins on that address and everything works as intended with reverse proxy until I try to add a windows Jenkins node. For that I have to have open custom port 99995 (port number is changed) so a windows based server could call master Jenkins on that port and register as a node.
I could be mistaken but I think the problem could be that that call isn’t http(s) request and redir is http redirect ( as it is said here: https://caddyserver.com/docs/caddyfile/directives/redir). Without reverse proxy everything works fine so the problem is definitely in my Caddyfile.

So it looks I was right.
If anyone interested I’ve found the solution for Jenkins here:


It is for Nginx but all settings for Jenkins are the same. Also I had to remove redir from the Caddyfile because redir isn’t needed with tunnel connection.
Sad I can’t make everything by using just Caddy but at least I’ve got everything running.

Oh, and I also had to remove

header_up X-Forwarded-Port {remote_port}

line from theheaders so Jenkins won’t argue about wrong reverse proxy settings. Maybe that would help someone.

1 Like