Access client ip inside nextcloud docker with haproxy docker - docker

I have a some docker container running and i want to see the real ip address from the client on the nextcloud docker logs. But currently i only can see the ip address from the haproxy container, i already added option forwardfor but still it does not work.
My docker-compose:
version: '3'
services:
db:
image: linuxserver/mariadb
restart: always
environment:
- MYSQL_ROOT_PASSWORD=
- PUID=100
- PGID=100
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=
volumes:
- /home/raspi/nextcloud-docker/volumen/mariadb/:/config
app:
image: nextcloud:apache
restart: always
volumes:
- /home/raspi/nextcloud-docker/volumen/nextcloud/:/var/www/html
environment:
- VIRTUAL_HOST=
- LETSENCRYPT_HOST=
- LETSENCRYPT_EMAIL=
- MYSQL_HOST=db
- OVERWRITEPROTOCOL=https
env_file:
- db.env
depends_on:
- db
networks:
- proxy-tier
- default
haproxy:
restart: always
image: haproxy:2.1.7
volumes:
- /home/raspi/nextcloud-docker/haproxy/config:/usr/local/etc/haproxy/
- /home/raspi/nextcloud-docker/haproxy/certs/haproxy/:/usr/local/etc/ssl/
ports:
- 8080:8080
networks:
- proxy-tier
depends_on:
- app
networks:
proxy-tier:
My haproxy.cfg:
global
maxconn 50
tune.ssl.default-dh-param 2048
log stdout format raw local0
defaults
log global
mode http
timeout tunnel 1h
timeout http-request 1h
timeout connect 20s
option forwardfor
option http-server-close
frontend https
bind *:8080 ssl crt /usr/local/etc/ssl/website.org
http-request redirect scheme https code 301 if !{ ssl_fc }
default_backend nextcloud
timeout client 1h
backend nextcloud
server app1 app:80
timeout server 1h
The nextcloud logs:
{"reqId":"GoyJSJ8Jl1xAUf9xARf6","level":2,"time":"2020-09-11T23:41:54+00:00","remoteAddr":"172.29.0.3","user":"--","app":"no app in context","method":"POST","url":"/login","message":"Login failed: malo (Remote IP: 172.29.0.3)","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36","version":"19.0.0.12"}
{"reqId":"A4n1pk3sU8Bsh0pkMjfB","level":2,"time":"2020-09-11T23:43:27+00:00","remoteAddr":"172.29.0.3","user":"--","app":"no app in context","method":"POST","url":"/login","message":"Login failed: malo3 (Remote IP: 172.29.0.3)","userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36","version":"19.0.0.12"}
As you can see, in only getting the ip address from the haproxy container. I already did add
option forwardfor to haproxy.cfg and did add
'trusted_proxies' => array('172.29.0.3'),
'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'),
and restarted but nothing worked. I need this to make fail2ban work.
What am i missing?

I had to make the proxy-tier network static so my networks look like this:
networks:
proxy-tier:
ipam:
config:
- subnet: 174.20.0.0/24
and the app and haproxy container i had to put this:
networks:
proxy-tier:
ipv4_address: 174.20.0.x
and now add the haproxy container ip address:
environment:
- TRUSTED_PROXIES=174.20.0.x
now it works!

Related

Issue with routing http flow with Traefik

I have a small lab setup on docker lab server where I have several containers. I wanted to set up a proxy with Traefik, but I stuck on one thing.
Looks like routing works fine but I am having err_connection_refused when I try to access routed services by the browser.
It works fine with the curl command.
Using DNSMasq to manage records - traefik for proxy.
Below docker-compose files for traefik and test container which I am using for testing the proxy.
Heimdall Dashboard:
---
version: "2.1"
services:
heimdall:
image: lscr.io/linuxserver/heimdall:latest
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /path/to/appdata/config:/config
restart: unless-stopped
labels:
- "traefik.http.routers.heimdall-www.rule=Host(`heimdall.lab`)"
- "traefik.http.services.heimdall-www.loadbalancer.server.port=80"
networks:
default:
name: traefik_default
Traefik container:
version: '3'
services:
reverse-proxy:
# The official v2 Traefik docker image
image: traefik:v2.9
# Enables the web UI and tells Traefik to listen to Docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
whoami:
# A container that exposes an API to show its IP address
image: traefik/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.lab`)"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
DNSmasq entry
address=/.lab/127.0.0.1
I dont understand why curling works fine e.g.:
curl -H Host:whoami.lab http://192.168.0.150
Hostname: 1ad1e42dd818
IP: 127.0.0.1
IP: 172.21.0.4
RemoteAddr: 172.21.0.2:54128
GET / HTTP/1.1
Host: whoami.lab
User-Agent: curl/7.84.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.0.100
X-Forwarded-Host: whoami.lab
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: ca631c80565a
X-Real-Ip: 192.168.0.100

How to set a DDNS in Traefik host?

I am new in Traefik and I am using that to make the reverse proxy for my docker images, and I want to use my local computer like a server that could be accessed externally.
Here is what I did:
I create a DDNS pointing to my external ip in No-Ip:
Host-name: myhost.ddns.net
Target/ip: my-external-ip
Type: A
I want to use Traefik, so I want to expose the http default port (80) and https default port (443), so I made the port-forward in my router:
Doing that, I expect that http or https requests is being redirect to my internal host, that is the one which is the server of my application
Create the docker-compose.yml and traefik.yml files:
docker-compose.yml:
version: '3.7'
services:
traefik:
image: traefik:v2.0.1
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- external
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.myhost.ddns.net`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=*user:password*
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.myhost.ddns.net`)"
# - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=http"
- "traefik.http.routers.traefik-secure.service=api#internal"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
*another-services-configs...*
networks:
external:
external: true
traefik.yml:
api:
dashboard: true
# Writing Logs to a File, in JSON
log:
level: DEBUG
filePath: "log-file.log"
format: json
# Configuring a buffer of 100 lines
accessLog:
filePath: "log-access.log"
bufferingSize: 100
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
http:
acme:
email: my-email#hotmail.com
storage: acme.json
httpChallenge:
entryPoint: http
Finally, when I run docker-compose up -d , the application goes on, but I can not acess the traefik dashboard when I try to access traefik.myhost.ddns.net in the browser. The error message is that could not be found any web site with that host.
But, if I change the Host-name in the label to - traefik.http.routers.traefik.rule=Host('traefik.localhost')" , I can access the traefik dashboard typing traefik.localhost in the browser.
The question is, how can I use my ddns in the Host label to be able to access my traefik server externally?

Traefik 2 docker not showing client real ip

I have traefik running in docker (on a windows host). The problem I have is that the X-Real-IP header alawys shows the docker network gateway ip instead of the real client ip. I'm not sure what I'm doing wrong, I know traefik in host network mode should work, but then it would no longer find the docker services on it's own.
This is my docker compose file:
version: "3.7"
networks:
t2_proxy:
external:
name: t2_proxy
default:
driver: bridge
services:
traefik:
# The official v2 Traefik docker image
image: traefik/traefik:latest
container_name: traefik
restart: unless-stopped
# Enables the web UI and tells Traefik to listen to docker
command: # CLI arguments
- --global.checkNewVersion=true
- --global.sendAnonymousUsage=true
- --entryPoints.https.address=:443
- --api=true
- --api.insecure=true
- --api.dashboard=true
- --log=true
- --log.level=INFO # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
- --accessLog=true
- --accessLog.filePath=/traefiklog/traefik.log
- --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
- --providers.docker=true
- --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.xxx.com`)
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.exposedByDefault=false
- --providers.docker.network=t2_proxy
- --providers.docker.swarmMode=false
- --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
- --providers.file.watch=true # Only works on top level files in the rules folder
networks:
t2_proxy:
ipv4_address: 192.168.90.254
ports:
- target: 443
published: 443
protocol: tcp
mode: host
volumes:
- C:\docker/traefik/rules:/rules
- /var/run/docker.sock:/var/run/docker.sock:ro
- C:\docker/traefik/logs:/traefiklog
- C:\docker/shared:/shared
labels:
- "traefik.enable=true"
whoami:
image: "containous/whoami"
container_name: "whoami"
networks:
t2_proxy:
ipv4_address: 192.168.90.200
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.xxx.com`)"
- "traefik.http.routers.whoami.entrypoints=https"
- "traefik.http.routers.whoami.tls=true"
I set up the network with:
docker network create --gateway 192.168.90.1 --subnet 192.168.90.0/24 t2_proxy
and this is the output of the whoami webrequest in the browser:
Hostname: 8752e7b8a5d4
IP: 127.0.0.1
IP: 192.168.90.200
RemoteAddr: 192.168.90.254:36228
GET / HTTP/1.1
Host: whoami.xxx.com:433
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US
Cache-Control: max-age=0
Dnt: 1
Te: trailers
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 192.168.90.1
X-Forwarded-Host: whoami.xxx.com:433
X-Forwarded-Port: 433
X-Forwarded-Proto: https
X-Forwarded-Server: 969f601c0c24
X-Real-Ip: 192.168.90.1
The solution seems to be presented in this guide: https://dockerswarm.rocks/traefik/#getting-the-client-ip
If you need to read the client IP in your applications/stacks using the X-Forwarded-For or X-Real-IP headers provided by Traefik, you need to make Traefik listen directly, not through Docker Swarm mode, even while being deployed with Docker Swarm mode.
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host

Port conflict in docker-compose

I am trying to create the following with a reverse proxy (the webs only work) but with the mail server, it gives port conflict error in docker-compose.
What I want is that the webs coexist with the mail service. For example mail.sitea.com
Any suggestion?
version: '3.4'
services:
nginx-proxy:
image: jwilder/nginx-proxy
restart: always
ports:
- 443:443
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
site-a:
image: nginx
restart: always
expose:
- '80'
volumes:
- /var/www/site-a/public_html/:/usr/share/nginx/html:ro
environment:
- VIRTUAL_HOST=sitea.com
site-b:
image: nginx
restart: always
expose:
- '80'
volumes:
- /var/www/site-b/public_html/:/usr/share/nginx/html:ro
environment:
- VIRTUAL_HOST=siteb.com
poste:
image: analogic/poste.io
restart: always
network_mode: "host"
expose:
- 25
- 80
- 443
- 110
- 143
- 465
- 587
- 993
- 995
volumes:
- /docker/mail:/data
environment:
- HTTPS=ON
- DISABLE_CLAMAV=TRUE
OUTPUT
/docker# vim /docker/docker-compose.yml
root#adroconstruccion:/docker# docker-compose up -d
Removing docker_nginx-proxy_1
docker_site-b_1 is up-to-date
docker_site-a_1 is up-to-date
Starting 08fba2b58471_docker_nginx-proxy_1 ... error
Recreating docker_poste_1 ...
ERROR: for 08fba2b58471_docker_nginx-proxy_1 Cannot start service nginx-proxy: driver failed programming external connectivity on endpoint 08fba2b58471_docker_nginx-proxy_1 (095659f459c1af8c729129074520b40800e528719727061bdbc4bfa25f6c37d5)Recreating docker_poste_1 ... done
ERROR: for nginx-proxy Cannot start service nginx-proxy: driver failed programming external connectivity on endpoint 08fba2b58471_docker_nginx-proxy_1 (095659f459c1af8c729129074520b40800e528719727061bdbc4bfa25f6c37d5): Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use
ERROR: Encountered errors while bringing up the project.
If you run poste with network_mode: "host" it will listen on those ports on the local network. So the port 443 listener in the poste service conflicts with nginx-proxy
Depending on what you're using the poste continer for you might be able to get away with just commenting out those ports (80 and 443) and just using the mail ports. Or you could remove the network_mode: "host" and maybe proxy them through nginx?

traefik 502 bad gateway after a certain time

Problem
I'm running traefik to serve a python django app inside an docker container. The app is running without problems over https or http. After a unspecific time (under an hour) traefik logs says "502 Bad Gateway" and my nginx and uwsgi logs dont say anything. "docker restart djangoapp" fixed the Problem for a short time.
Setup
Internet -> traefik -> nginx -> uwsgi -> djangoapp
traefik.toml
debug = true
defaultEntryPoints = ["http", "https"]
# Access log
[traefikLog]
filePath = "/var/log/traefik/traefik.log"
format = "json"
[accessLog]
filePath = "/var/log/traefik/access.log"
format = "json"
[web]
address = ":8080"
[web.auth.basic]
users = ["admin:XXX/"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "/etc/ssl/traefik/cert-register.stupa.pem"
keyFile = "/etc/ssl/traefik/key-register.stupa.key"
docker-compose.yml traefik
version: '2'
services:
frontproxy:
image: traefik
container_name: frontproxy
command: --api --docker --docker.domain=docker.localhost
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- $PWD/traefik.toml:/traefik.toml
- /srv/ssl/certs:/etc/ssl/traefik
- /srv/frontproxy/logs:/var/log/traefik
networks:
default:
external:
name: frontproxy
docker-compose djangoapp
version: '3'
networks:
helfertoolnet:
frontproxy:
external: true
volumes:
postgresVolume:
services:
helfertool_app:
image: helfertool
hostname: helfertool_app
command: [/usr/bin/supervisord]
container_name: helfertool_app
volumes:
- /srv/helfertool/conf/nginx/helfertool.conf:/etc/nginx/sites-enabled/helfertool.conf
- /srv/helfertool/conf/helfertool/settings_local.py:/app/helfertool/helfertool/settings_local.py
- /srv/helfertool/conf/nginx/logs:/var/log/nginx
- /srv/helfertool/conf/supervisor:/etc/supervisor/conf.d
- /srv/helfertool/conf/uwsgi:/etc/uwsgi/apps-enabled
depends_on:
- "helfertool_rabbitmq"
- "helfertool_db"
labels:
- traefik.backend=helfertool
- traefik.frontend.rule=Host:XXX
- traefik.docker.network=frontproxy
- traefik.port=80
- traefik.frontend.entryPoints=http,https
networks:
- frontproxy
- helfertoolnet
helfertool_rabbitmq:
image: rabbitmq:3
hostname: helfertool_rabbitmq
container_name: helfertool_rabbitmq
environment:
- RABBITMQ_DEFAULT_USER=XXX
- RABBITMQ_DEFAULT_PASS=XXX
- RABBITMQ_DEFAULT_VHOST=XXX
networks:
- helfertoolnet
helfertool_db:
image: postgres
command: postgres -c listen_addresses='*'
hostname: helfertool_db
container_name: helfertool_db
environment:
- POSTGRES_PASSWORD=XXX
- POSTGRES_USER=XXX
volumes:
# Persist the data between container invocations
- postgresVolume:/var/lib/postgresql/data
networks:
- helfertoolnet
Logs
traefik log
{"BackendAddr":"172.18.0.7:80",
"BackendName":"backend-helfertool",
"BackendURL":
{"Scheme":"http",
"Opaque":"",
"User":null,
"Host":"172.18.0.7:80",
"Path":"",
"RawPath":"",
"ForceQuery":false,
"RawQuery":"",
"Fragment":""},
"ClientAddr":"141.60.38.168:60979",
"ClientHost":"141.60.38.168",
"ClientPort":"60979",
"ClientUsername":"-"
,"DownstreamContentSize":11,
"DownstreamStatus":502,
"DownstreamStatusLine":"502 Bad Gateway",
"Duration":1074690,
"FrontendName":"Host-register-stupa-fh-rosenheimde-0",
"OriginContentSize":11,
"OriginDuration":855550,
"OriginStatus":502,
"OriginStatusLine":"502 Bad Gateway",
"Overhead":219140,
"RequestAddr":"register.stupa.fh-rosenheim.de",
"RequestContentSize":0,
"RequestCount":27132,
"RequestHost":"register.stupa.fh-rosenheim.de",
"RequestLine":"GET / HTTP/1.1",
"RequestMethod":"GET",
"RequestPath":"/",
"RequestPort":"-",
"RequestProtocol":"HTTP/1.1",
"RetryAttempts":0,
"StartLocal":"2018-05-25T12:55:18.619598232Z",
"StartUTC":"2018-05-25T12:55:18.619598232Z",
"level":"info",
"msg":"",
"request_Accept":"text/html,application/xhtml+xml,
application/xml;q=0.9,*/*;q=0.8",
"request_Accept-Encoding":"gzip,deflate",
"request_Accept-Language":"de,en-US;q=0.7,en;q=0.3",
"request_Cache-Control":"max-age=0",
"request_Connection":"keep-alive",
"request_Cookie":"csrftoken=awELtrVSPImPNZFNph6SYs0eJuAZcjIzX462ykgUip1hQVQagaaKQxZhFUbzUrS5;
sessionid=4bcrynx0qyu2bam1nf8eewiurv0vtn5a",
"request_Referer":"http://register.stupa.fh-rosenheim.de/weinfest2018/",
"request_Upgrade-Insecure-Requests":"1",
"request_User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0","time":"2018-05-25T12:55:18Z"}
Thank you :)
Might be the case that your uswgi container restarted and got a new ip address in docker, so nginx couldn't resolve it.

Resources