Elmin
Elmin

Reputation: 11

Docker nginx proxy, open ldap and phpldapadmin - unable to access ldap admin through nginx

I think that I have misconfiguration issue in my environment, and I would like to hear your opinions about it. Advice or help to solve it would be more than welcome.

Description: I have problem with accessing to LDAP Admin using jwilder/nginx-proxy container over the virtual hostname while accessing through real linux hostname with an exposed port works fine. Access is with HTTPS using valid wildcard certificate.

Environment: I am running docker on linux (CentOS 7) and I want to setup one docker container with jwilder/nginx-proxy and additional two docker containers: one for openLdap, second one for phpLdapAdmin. So access to my ldapadmin will be through nginx, without exposing ports.

Steps done so far:

1. Create container - nginx proxy

docker run -d -p 80:80 -p 443:443 \
  -v /home/admin/nginx/certs:/etc/nginx/certs \
  -v /var/run/docker.sock:/tmp/docker.sock:ro \
  --name proxy \
  jwilder/nginx-proxy

2. Create container - ldap

docker run --name ldap -p 636:636 \ 
 -v /home/admin/nginx/certs:/container/service/slapd/assets/certs \
 -v /data/slapd/database:/var/lib/ldap \
 -v /data/slapd/config:/etc/ldap/slapd.d \
 --hostname ldap.company.com \
 --add-host=ldap.company.com:192.168.168.168 \
 --env LDAP_ORGANISATION='Company ltd' \
 --env LDAP_DOMAIN='company.com' \
 --env LDAP_ADMIN_PASSWORD='Password' \
 --detach osixia/openldap:1.2.2 \

Instead of "192.168.168.168" is my real public IP address

Then successfully search for LDAP

docker exec ldap \
  ldapsearch -x -H ldap://ldap.company.com \
  -b dc=company,dc=com \
  -D "cn=admin,dc=company,dc=com" \
  -w Password\

3. Create container phpldapadmin

docker run \
 --name ldapadmin \
 --env PHPLDAPADMIN_LDAP_HOSTS=ldap.company.com \ 
 --expose 389 \
 -e VIRTUAL_HOST=ldap.company.com \
 -e VIRTUAL_PORT=389 \
 --volume /home/admin/nginx/certs:/container/service/phpldapadmin/assets/apache2/certs \
--env PHPLDAPADMIN_HTTPS_CRT_FILENAME=ldap.company.com.crt \
--env PHPLDAPADMIN_HTTPS_KEY_FILENAME=ldap.company.com.key \
--env PHPLDAPADMIN_HTTPS_CA_CRT_FILENAME=ldap.company.com.crt \
--detach osixia/phpldapadmin:0.7.2

And finally restart nginx proxy container to automatically add ldap and ldapadmin to nginx configuration.

docker restart proxy

Then I get this exposed ports:

IMAGE PORTS NAMES

osixia/phpldapadmin:0.7.2 80/tcp, 389/tcp, 443/tcp ldapadmin

osixia/openldap:1.2.2 389/tcp, 0.0.0.0:636->636/tcp ldap

Now comes the strange part, hostname of my Linux server is dev.company.com with some public address, and I can access my ldapadmin with https://dev.company.com:6443, but I can not access through URL: ldap.company.com, without exposing ports. I can not ping ldap.company.com.key on Linux host itself.

Note: I have done the same thing for Jenkins:

docker run -d --rm -u root -v /var/run/docker.sock:/var/run/docker.sock -v jenkins-data:/var/jenkins_home -v "$HOME":/home -e VIRTUAL_HOST=jenkins.company.com -e VIRTUAL_PORT=8080 --name nj jenkins

and for artifactory:

docker run --name artifact -d -v /var/opt/jfrog/artifactory:/var/opt/jfrog/artifactory -e VIRTUAL_HOST=artifactory.company.com -e VIRTUAL_PORT=8081 artifactory-oss

and for both of these two i have URL's which are pingable, they return my public IP address and I successfully access them through browser: jenkins.company.com and artifactory.company.com

I can not ping ldap.company.com.key on Linux host itself.

Upvotes: 1

Views: 3246

Answers (3)

M4n1us
M4n1us

Reputation: 31

For those stumbling in the dark: As the proxy is handling the HTTPS stuff you don't need apache for that hence you run the phpldapadmin with the following env variables:

environment:
  - PHPLDAPADMIN_TRUST_PROXY_SSL=true
  - PHPLDAPADMIN_HTTPS=false

You do not expose any ports for the docker image as the nginx-proxy handles all the networking internally.

Was having the same issue but this resolved, thought about doing it this way because that's how the letsencrypt-proxy-companion sets up the "advanced setup"

Upvotes: 3

Elmin
Elmin

Reputation: 11

As I can not describe in detail my current state in above comments, I will write this as partial answer as I can access when I specify port in my URL. Recap of my environment is this:

1. Create container - nginx proxy

docker run -d -p 80:80 -p 443:443 \
  -v /home/admin/nginx/certs:/etc/nginx/certs \
  -v /var/run/docker.sock:/tmp/docker.sock:ro \
  --name proxy \
  jwilder/nginx-proxy

2. Create container -LDAP

docker run --name ldap \
 -v /home/admin/nginx/certs:/container/service/slapd/assets/certs \
 -v /data/slapd/database:/var/lib/ldap -v /data/slapd/config:/etc/ldap/slapd.d \
 --hostname ldap.company.com --add-host=ldap.company.com:192.168.168.168 \
 --expose 443 \
 --env LDAP_ORGANISATION='Company ltd' \
 --env LDAP_DOMAIN='company.com' \
 --env LDAP_ADMIN_PASSWORD='Password' \
 -e VIRTUAL_HOST=ldap.company.com \
 -e VIRTUAL_PORT=443 \
 --detach osixia/openldap:1.2.2

3. Create container - PHPLDAPADMIN

docker run --name ldapadmin \
 -p 6443:443 \
 --env PHPLDAPADMIN_LDAP_HOSTS=ldap.company.com \
 -e VIRTUAL_HOST=ldap.company.com \
 -e VIRTUAL_PORT=443 \
 --expose 443 \
 --hostname ldap.company.com \
 --volume /home/admin/nginx/certs:/container/service/phpldapadmin/assets/apache2/certs \
 --env PHPLDAPADMIN_HTTPS_CRT_FILENAME=ldap.company.com.crt \
 --env PHPLDAPADMIN_HTTPS_KEY_FILENAME=ldap.company.com.key \
 --env PHPLDAPADMIN_HTTPS_CA_CRT_FILENAME=ldap.company.com.crt \
 --detach osixia/phpldapadmin:0.7.2\

Configuration in nginx: cat /etc/nginx/conf.d/default.conf

# ldap.company.com
upstream ldap.company.com {
            ## Can be connected with "bridge" network
        # ldapadmin
        server 172.17.0.5:443;
            ## Can be connected with "bridge" network
        # ldap
        server 172.17.0.4:443;
}
server {
server_name ldap.company.com;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
return 301 https://$host$request_uri;
}
server {
  server_name ldap.company.com;
  listen 443 ssl http2 ;
  access_log /var/log/nginx/access.log vhost;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
  ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-******************';
  ssl_prefer_server_ciphers on;
  ssl_session_timeout 5m;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;
  ssl_certificate /etc/nginx/certs/ldap.company.com.crt;
  ssl_certificate_key /etc/nginx/certs/company.com.key;
  add_header Strict-Transport-Security "max-age=31536000" always;
  location / {
    proxy_pass http://ldap.company.com;
  }
}

Running containers:

[admin@dev ~]$ docker ps
CONTAINER ID  IMAGE                      COMMAND                  CREATED          STATUS         PORTS                                   NAMES
4c021b9f85e4  osixia/phpldapadmin:0.7.2  "/container/tool/run"    9 minutes ago    Up 9 minutes   80/tcp, 0.0.0.0:6443->443/tcp            ldapadmin
53963bfe8fdc  osixia/openldap:1.2.2      "/container/tool/run"    10 minutes ago   Up 10 minutes  389/tcp, 443/tcp, 636/tcp                   ldap
c9576b8c1b72  jwilder/nginx-proxy        "/app/docker-entrypo…"   10 days ago      Up 21 minutes  0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   proxy

Log from nginx when i call http://ldap.company.com in browser: - FAILED

nginx.1    | 2018/11/19 12:46:11 [error] 32#32: *1 upstream prematurely closed connection while reading response header from upstream, client: X:X:X:X, server: ldap.company.com, request: "GET / HTTP/2.0", upstream: "http://172.17.0.5:443/", host: "ldap.company.com"
nginx.1    | 2018/11/19 12:46:11 [error] 32#32: *1 connect() failed (111: Connection refused) while connecting to upstream, client: X:X:X:X, server: ldap.company.com, request: "GET / HTTP/2.0", upstream: "http://172.17.0.4:443/", host: "ldap.company.com"

Log from nginx when i call https://ldap.company.com:6443 in browser - SUCCESS

nginx.1    | ldap.company.com X:X:X:X - - [19/Nov/2018:12:46:11 +0000] "GET / HTTP/2.0" 502 575 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

[admin@dev ~]$

Questions that cross my mind are:

  1. Am I creating containers the right way?
  2. During the creation of ldap container, do I need to specify some ports -p XXX:XX?
  3. Do I need to export ports on ldap and ldapadmin as well, like I did using -expose switch?
  4. What I am doing wrong?

Thanks in advance everyone who can help and specially you weibeld, for your time and valuable comments.

Additonal info:

On the NGINX container I get these error:

nginx.1    | ldap.bitconex.de 62.216.206.17 - - [20/Nov/2018:15:52:49 +0000] "GET / HTTP/2.0" 403 209 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

Since I get the error on ldapadmin:

[Tue Nov 20 15:18:23.807278 2018] [authz_core:error] [pid 1019:tid 140081490781952] [client 172.17.0.3:59916] AH01630: client denied by server configuration: /var/www/html
172.17.0.3 - - [20/Nov/2018:15:18:23 +0000] "GET / HTTP/1.1" 403 373 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

I have searched ldap-admin container to check in which files is mentioned /var/www/html, and I have found taht is mention on two places:

1.

root@d65a1005d5aa:/# grep -rnw '/var/' -e '/var/www/html'
/var/lib/dpkg/info/apache2.postinst:111:        for dir in /var/www 
/var/www/html ; do
/var/lib/dpkg/info/apache2.postinst:124:            cp 
/usr/share/apache2/default-site/index.html /var/www/html/index.html
/var/lib/dpkg/info/apache2.postinst:128:        for dir in /var/www 
/var/www/html ; do
/var/lib/dpkg/info/apache2.postrm:70:   if is_default_index_html 
/var/www/html/index.html ; then
/var/lib/dpkg/info/apache2.postrm:71:       rm -f 
/var/www/html/index.html
/var/lib/dpkg/info/apache2.list:223:/var/www/html

2.

root@d65a1005d5aa:/container/service/:apache2/assets/sites-available# 
ls
000-default.conf
root@d65a1005d5aa:/container/service/:apache2/assets/sites-available# 
cat 000-default.com
<VirtualHost *:80>
     # The ServerName directive sets the request scheme, hostname and port that
     # the server uses to identify itself. This is used when creating
     # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
   #ServerName www.example.com

   ServerAdmin webmaster@localhost
   DocumentRoot /var/www/html

   # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
   # error, crit, alert, emerg.
   # It is also possible to configure the loglevel for particular
   # modules, e.g.
   #LogLevel info ssl:warn

   # For most configuration files from conf-available/, which are
   # enabled or disabled at a global level, it is possible to
   # include a line for only one particular virtual host. For example the
   # following line enables the CGI configuration for this host only
   # after it has been globally disabled with "a2disconf".
   #Include conf-available/serve-cgi-bin.conf

   <Directory /var/www/html >
       Require all granted
   </Directory>

</VirtualHost>

So I am not sure do I need to manually create this html folder or edit this file in place 2, and put the path to phpadmin config file: root@d65a1005d5aa:/container/service/phpldapadmin/assets/config# ls config.php README.md

Or maybe put the path to the /var/www/phpldapadmin_bootstrap/htdocs?

Upvotes: 0

weibeld
weibeld

Reputation: 15282

First of all, you can check the logs of the jwilder/nginx-proxy if it actually receives any requests:

docker logs -f CONTAINER_ID

But if you can't even ping ldap.company.com, then probably the domain can't be resolved to an IP address, because there is no DNS record for it. You can test this with:

host ldap.company.com

If the domain can't be resolved, then create a DNS A record in the company.com DNS server that points ldap.company.com to the public IP address of your host.

Or you can test if everything works already before, if you just make the PHPLDAPAdmin requests to the public IP address of your host rather than the ldap.company.com domain.

Upvotes: 0

Related Questions