1

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.

Elmin
  • 11
  • 1
  • 6
  • I think the question is well posed, but please format all the code blocks like I i did it for the first one in your question. Otherwise, the code is very unreadable. – weibeld Nov 16 '18 at 18:03
  • I just saw in the documentation of [`jwilder/nginx-proxy`](https://hub.docker.com/r/jwilder/nginx-proxy/) that *"the containers being proxied must expose the port to be proxied"*. You try to route traffic to the port 389 of the `osixia/phpldapadmin:0.7.2` container, but if I run this container, I see that port 389 is not exposed (only ports 80 and 443 by default). Can you try to add `--expose 389` to the command that starts the `osixia/phpldapadmin:0.7.2` container and see if it works? – weibeld Nov 16 '18 at 18:08
  • I have format code block as you suggested. And also paste new command to create ldapadmin container. Result is the same, i can not ping ldap.company.com. In the question I have pasted output of the docker ps command so you can see exposed ports. maybe to try create ldap container with exposed 389 port?? – Elmin Nov 16 '18 at 19:05
  • Can you check the logs of the `jwilder/nginx-proxy` container if it actually receives any requests? Do you have a DNS record for `ldap.company.com`? If you can't ping `ldap.company.com` I think it has nothing to do with NGINX, but with DNS resolution or with a firewall or other security settings. – weibeld Nov 16 '18 at 19:55
  • That is interesting, call of ldap.company.com is not recorded in jwilder/nginx-proxy. But from the other hand, if I can not ping it, than it can not be recorded in logs of nginx-proxy. I didn't change DNS records for jenkins.company.com and for artifactory.company.com. It is automatically done after restart of nginx-proxy. I have also turn off firewall and selinux, but without success. Perhaps is something with DNS, but I am not sure what exactly. – Elmin Nov 16 '18 at 20:35
  • Linux resolv.conf is not changed. I am not sure how it can automatically resolve jenkins.company.com and not ldap.company.com?When I ping jenkins reply ip is public ip address of my servev, not the address of the jenkins container. Is there a some kind of docker DNS?? – Elmin Nov 16 '18 at 20:46
  • Try `host ldap.company.com`. If it returns nothing, then it's a DNS issue. If `jenkins.company.com` works, it must be resolved somewhere. You can find out the DNS server that resolves this domain with `nslookup -type=soa jenkins.company.com`. – weibeld Nov 16 '18 at 22:20
  • I will have to check with DNS zone, but still I am confused how it can resolve jenkis.company.com and not ldap.company.com? [admin@dev ~]$ host ldap.bitconex.de host ldap.company.com Host ldap.company.com not found: 3(NXDOMAIN) [admin@dev ~]$ nslookup -type=soa jenkins.company.com Server: X.X.X.X Address: X.X.X.X#53 Non-authoritative answer: *** Can't find jenkins.bitconex.de: No answer Authoritative answers can be found from: company.com origin = ns.****.com mail addr = hostmaster.****.com serial = 20181 refresh = 40000 retry = 7200 expire = 604800 minimum = 300 – Elmin Nov 16 '18 at 22:47
  • [admin@dev ~]$ nslookup -type=soa ldap.company.com Server: X.X.X.X Address: X.X.X.X#53 ** server can't find ldap.company.com: NXDOMAIN – Elmin Nov 16 '18 at 22:48
  • I have checked DNS setup on webhosting, ldap.company.com was missing, and there was jenkins.company.com. I don't remember when I add that to DNS. Now I will wait for DNS propagation, and check in the morning. I will let you result tomorrow. – Elmin Nov 16 '18 at 23:29
  • Ok, I added this as a tentative answer. – weibeld Nov 17 '18 at 00:27

3 Answers3

2

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"

M4n1us
  • 21
  • 2
0

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.

weibeld
  • 13,643
  • 2
  • 36
  • 50
  • Thanks for suggestion. I have added DNS A record and test ping to ldap.company.com it works. When I try to call ldap.company.com through the browser i get : 502 Bad Gateway, which means that nginx redirection is wrong. What do you mean by: if you just make the PHPLDAPAdmin requests to the public IP address of your host rather than the ldap.company.com domain? – Elmin Nov 17 '18 at 14:16
  • When I expose ports -p 6443:443, i can access https://ldap.company.com:6443/ through browser, but still can not access by ldap.company.com . – Elmin Nov 17 '18 at 14:34
  • You mean expose port `-p 6443:443` on the NGINX container and then it works? Maybe you can find out something in the NGINX logs. – weibeld Nov 17 '18 at 17:09
  • No, not on the nginx, on the ldapadmin. When I create continer ldapadmin with command docker run -p 6443:443 --name bce-ldapadmin . . . rest of the command, then i can access by ldap.company.com:6443 through browser. Is it even possible to access ldapadmin without port 6443?? – Elmin Nov 17 '18 at 20:40
  • So then you access ldapadmin on port 443 (container port). But your NGINX routes traffic to port 389 of ldapadmin. Why do you use 389, and shouldn't it work if you use 443 instead of 389? – weibeld Nov 18 '18 at 00:49
0

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?

Elmin
  • 11
  • 1
  • 6
  • NGINX does the TLS termination and then sends unencrypted HTTP to phpldapadmin on port 443 (because you have set `-e VIRTUAL_PORT=443`). However, phpldapadmin expects HTTPS on port 443, and HTTP should go to port 80, so that could be the reason that phpldapadmin rejects the connection. Try with `-e VIRTUAL_PORT=80`. Also, you set up TLS termination with phpldapadmin, but the point of using NGINX is to not have to do this with the backend services, but only with NGINX. So, in the end, all the certificate configurations for phpldapadmin shouldn't be necessary. – weibeld Nov 19 '18 at 16:40
  • You mean to create ldapadmin with -e VIRTUAL_PORT=80, and delete certificates from the ldapadmin creation? – Elmin Nov 19 '18 at 16:47
  • When I create ldapadmin with virtual port 80, and delete certificates, I get error: You don't have permission to access / on this server. when I try access with ldap.company.com, over https I get error about certificates and unsecured connection. – Elmin Nov 19 '18 at 17:02
  • So, with `-e VIRTUAL_PORT=80` the redirection seems to work. The "permission denied" error comes from phpldapadmin, right? Probably it requires some authentication. When you delete the certificates from phpldapadmin, the only way to access it is `http://ldap.company.com` (redirected to https by NGINX) and `https://ldap.company.com`. But not `https://ldap.company.com:6443`, this shouldn't work anymore. – weibeld Nov 19 '18 at 17:57
  • Yes, you were right. I have checked the the logs of the ldapadmin container end found this error: [client 172.17.0.3:59732] AH01630: client denied by server configuration: /var/www/html 172.17.0.3 - - [19/Nov/2018:18:14:10 +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" – Elmin Nov 19 '18 at 18:15
  • config.php on the location:/var/www/phpldapadmin/config has some strange permission:-r-------- 1 www-data www-data 2432 Nov 19 18:36 config.php. As soon as I change permission and owner, after I restart container everything is the same. I can not copy this file outside the container to change it on my host. – Elmin Nov 19 '18 at 18:50
  • You can change the file on your host if you start the container with `-v /some/local/dir:/var/www/phpldapadmin/config`. – weibeld Nov 19 '18 at 19:15
  • I have already try that, but when I better take a look at the error:AH01630: client denied by server configuration: /var/www/html, I saw that trouble is in the html folder itself. It is not in the folder /var/www, and I can not find it in the ldapadmin container. Very strange behavior. – Elmin Nov 19 '18 at 19:18
  • Could it be [this](https://stackoverflow.com/questions/18392741/apache2-ah01630-client-denied-by-server-configuration)? If you start the container with `-p 81:80` and access it with `http://ldap.company.com:81`, it's the same problem? – weibeld Nov 19 '18 at 19:37
  • When I start container with -p 81:80 and try your suggestion I get error in browser: ERR_SSL_PROTOCOL_ERROR. I will check the URL that yo have pasted. I have already seen this URL, but I will have to first mount the config.php to add some sections in it. If you have other suggestion just write it here, and I will check it. Thank you very much. – Elmin Nov 19 '18 at 19:57
  • I am stuck with the "permission denied" error, and I don't know what to do next. I will edit my answer with a couple of more info like Nico has suggested. – Elmin Nov 20 '18 at 15:29
  • I would maybe replace the initial question with the text of this answer, as it's much clearer. – weibeld Nov 20 '18 at 16:59
  • I think it's an authorization error and has to do with the conf file. Try to search for [this](https://www.google.ca/search?ei=_zn0W6qgOuTR5gLaqr-4CQ&q=AH01630%3A+client+denied+by+server+configuration+%22require+all+granted%22&oq=AH01630%3A+client+denied+by+server+configuration+%22require+all+granted%22). For example trying [this](https://serverfault.com/a/699819) answer. – weibeld Nov 20 '18 at 17:04