Letsencrypt certificate with Tomcat and Certbot connection refused

Hi,

I cannot get the certificate for my domain with Certbot from Letsencrypt. I’ve already tried with different approaches but I couldn’t get it work.

I’m using Tomcat 9 and Ubuntu Server 17.10.

sudo certbot certonly --webroot -w /opt/tomcat/webapps -d domain.pl -d www.domain.pl
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for domain.pl
http-01 challenge for www.domain.pl
Using the webroot path /opt/tomcat/webapps for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. domain.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://domain.pl/.well-known/acme-challenge/Mf7iJgWMu_zJQii3tfBbm8f7LvSPZgp408DpN2G_79Y: Connection refused, www.domain.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://www.domain.pl/.well-known/acme-challenge/xYi47FqPW7q4xmq_bTEf-puXUahFbsrmkcIH6emdB2E: Connection refused

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: domain.pl
   Type:   connection
   Detail: Fetching
   http://domain.pl/.well-known/acme-challenge/Mf7iJgWMu_zJQii3tfBbm8f7LvSPZgp408DpN2G_79Y:
   Connection refused

   Domain: www.domain.pl
   Type:   connection
   Detail: Fetching
   http://www.domain.pl/.well-known/acme-challenge/xYi47FqPW7q4xmq_bTEf-puXUahFbsrmkcIH6emdB2E:
   Connection refused

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.

Earlier I had received in logs that I can’t reach connection with port 8443 and I should use 443 I tried to change something in Tomcat config and now I have something like I posted above:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    
      <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />
      </GlobalNamingResources>
    
      <Service name="Catalina">
    
        <Connector port="80" protocol="HTTP/1.1"
                   connectionTimeout="20000" />
    
    	    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
                   clientAuth="false" sslProtocol="TLS" 
                   KeystoreFile="/home/tomcat/.keystore"
    	       keystorePass="pass" />
    		   
    		   <Connector executor="tomcatThreadPool" port="443" protocol="HTTP/1.1" 
    		   scheme="https" secure="true" SSLEnabled="true" KeystoreFile="/home/tomcat/.keystore"
    	       keystorePass="pass">
    			</Connector>
    
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    
        <Engine name="Catalina" defaultHost="localhost">
    
          <Realm className="org.apache.catalina.realm.LockOutRealm">
    
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
          </Realm>
    
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                   prefix="localhost_access_log" suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    
          </Host>
        </Engine>
      </Service>
    </Server>

I know there are plenty of threads with hints how to cope with similar situations, but as I said, I couldn’t get it to work and I don’t know what I’m doing wrong. I would be very grateful regarding this specific configuration of mine. Thanks for any help.

Redacting the domain in your output means that we have to guess what’s wrong rather than being able to tell you.

The issue appears relatively straightforward.

From the outside internet, visiting your domain (domain.pl) isn’t working, because the server is not listening on the IP address that the domain points to.

Tomcat needs to be up and running while you try to issue the certificate, as it is being relied upon to serve the webroot challenge.

Thank you for your reply.

Tomcat is up and running and I can access my domain (without any port specified so I suppose it is 443), however I get a notification in my browser that the connection is unsecure. I can view my root app, so I suppose it is accessible in some way.

I tried to change connectors in configuration in order to redirect to port 443. Earlier I had 8443 on the address bar and then Certbot said that 8443 is not supposed to be the right port to perform the certification. I don’t know if my changes broke anything, but I did not know what to do with the previous warning (about the port 8443) either.

Do you have any ideas what else I could be looking for then? Or additional info I could provide in order for this error to become more self-explanatory?

Sorry that I’m such a noob in this subject, I tried to read a lot but I don’t have idea what to do now…

You should still tell us your domain name. For example, perhaps you don’t have an IPv6 connection the way that the certificate authority does, or perhaps you’re using Chrome which falls back to IPv4 in case of some kinds of connection failure (unlike the certificate authority). So your browser test might not reflect what the CA is seeing.

Okay, thank you, my domain name is nombritech.pl and I have only tomcat there with my app placed in the root folder and some other apps also in their separate contexts.

I had a certificate earlier but it expired, I do not know how I managed to do this last time, since then I changed something in tomcat connectors, maybe that could be an issue. I thought that maybe something is wrong and deleted the old certificate, but it didn’t help.

I would like to have the certificate that is valid for www.nombritech.pl and nombritech.pl because last time I managed to do this only without the host name (nombritech.pl).

EDIT: Once I managed to do it today but it turned out that the certificate is self-signed! I was following one of the tutorials here on forum: Configuring Let's Encrypt with Tomcat 6.x and 7.x

Thanks!

So, you’re trying to use --webroot, which uses an inbound HTTP connection on port 80 to validate your control of the domain name. However, you don’t currently have any web server listening on that port.

https://nombritech.pl/ shows the expired certificate error (which is expected if your certificate has expired)

http://nombritech.pl/ (trying to connect on port 80) shows the connection refused

Did you previously have a different web server also listening on port 80 that you have disabled? This is still a requirement for renewals using the --webroot method.

If you don’t want to have a web server listening on port 80 all of the time, you can instead use --standalone --preferred-challenges http-01, which will create a temporary web server on port 80 for you in order to complete the authentication challenge.

If I understand you correctly, do I need to have something like Apache or Nginx in first place? The last time I played with nginx too and I think I could do it because I had nginx then.

It is not possible that Tomcat only listens on port 80 and plays the role of the web server for certification purposes? Sorry if it is a noob question…

The last thing you mentioned about standalone web server means that it vanishes and is used only for authentication purpose, right?

I think I’d rather have only Tomcat because I don’t need a web server like apache or nginx on my server so if it is possible not to have it running all the time I would definitely go that way

The Certbot standalone feature will run a temporary web server on port 80, only for the lifetime of the validation request. It will not listen the remainder of the time.

You don’t need to add Apache or nginx.

Your could also configure Tomcat to also listen on port 80, should you feel better about doing it that way.

Thanks :slight_smile:

So I tried to use

sudo certbot certonly --standalone --preferred-challenges http-01 -d nombritech.pl -d www.nombritech.pl

and I get something like this:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for nombritech.pl
http-01 challenge for www.nombritech.pl
Cleaning up challenges
Problem binding to port 80: Could not bind to IPv4 or IPv6.

I would like Certbot to create the mentioned temporary web server on port 80. Is my Tomcat configuration now messing something with this or the command I’m using is wrong?

Hello,

The command is correct, but it looks like something may already be listening on port 80.

You can list what is listening with:

sudo ss -tlnp

You can try check what the reason for the inability to listen is by installing netcat/nc and trying:

sudo nc -vvv -l -p80

It’s also possible that Tomcat is already listening on port 80, but you have a firewall rule blocking access to it from the outside internet.

Hello and thank you :slight_smile:

I think that Tomcat is listening:

LISTEN 0 100 :::80 :::* users:(("java",pid=7199,fd=37))

Maybe it is then blocked by firewall, I’ve already tried to unlock ports in iptables, but maybe I did something wrong:

root@vps366782:~# sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8443 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT

Your firewall is definitely misconfigured. For example, your Postgres server is currently exposed to the internet, which I am guessing is not consistent with your intent.

I can suggest firewalld or ufw as high level/user-friendly alternatives to using iptables raw.

Okay, thanks I choose UFW :wink:

I reset my rules and added some basic just for now to do this certificate. This is my configuration:

root@vps366782:~# sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
443/tcp                    ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
22                         ALLOW IN    Anywhere
443/tcp (v6)               ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
22 (v6)                    ALLOW IN    Anywhere (v6)

I also changed Tomcat configuration to the previous one as I still had the same error as previous with port binding and now I have this again:

Failed authorization procedure. www.nombritech.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching https://www.nombritech.pl:8443/.well-known/acme-challenge/LerD9kbZV3mJmqVftnPinrrb0FBgJ4eFLcSU9mspmnY: Invalid port in redirect target. Only ports 80 and 443 are supported, not 8443, nombritech.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching https://nombritech.pl:8443/.well-known/acme-challenge/pf5jkeqBKOW4Ibw1rXUma6qwWguX45Z68_V_qEuMXRY: Invalid port in redirect target. Only ports 80 and 443 are supported, not 8443

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: www.nombritech.pl
   Type:   connection
   Detail: Fetching
   https://www.nombritech.pl:8443/.well-known/acme-challenge/LerD9kbZV3mJmqVftnPinrrb0FBgJ4eFLcSU9mspmnY:
   Invalid port in redirect target. Only ports 80 and 443 are
   supported, not 8443

   Domain: nombritech.pl
   Type:   connection
   Detail: Fetching
   https://nombritech.pl:8443/.well-known/acme-challenge/pf5jkeqBKOW4Ibw1rXUma6qwWguX45Z68_V_qEuMXRY:
   Invalid port in redirect target. Only ports 80 and 443 are
   supported, not 8443

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.

My Tomcat server.xml right now:

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />

  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>

    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
	
	    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               KeystoreFile="/home/tomcat/.keystore"
	       keystorePass="pass" />
		   
		   <Connector executor="tomcatThreadPool" port="443" protocol="HTTP/1.1" 
		   redirectPort="8443" scheme="https" secure="true" SSLEnabled="true" KeystoreFile="/home/tomcat/.keystore"
	       keystorePass="pass">
			</Connector>

    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">

        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

What should I do now? :frowning: Something is missconfigured, that was not only the firewall I guess…

With your current error, the problem is the redirect to port 8443 - it is not acceptable for Let’s Encrypt:

$ curl -i nombritech.pl/.well-known/acme-challenge/haha
HTTP/1.1 302
Cache-Control: private
Expires: Thu, 01 Jan 1970 01:00:00 CET
Location: https://nombritech.pl:8443/.well-known/acme-challenge/haha

You may only redirect to port 80 or 443 if you want the webroot challenge to succeed.

I believe the solution would be to configure Tomcat to instead redirect to the 443 HTTPS listener.

I think this is the problem:

redirectPort="8443"

Change that to port 80 443, restart Tomcat, and run a curl test to ensure that it is correctly redirecting to 443.

should have searched JKS :wink:

walk through the whole article

Andrei

Still nothing, I’m getting only this:

Problem binding to port 80: Could not bind to IPv4 or IPv6.

For the last few hours I’ve been trying to configure Tomcat properly, this is what I ended with right now:

  <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000"/>
	  
  <Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" KeystoreFile="/home/tomcat/.keystore" keystorePass="pass" />
  
root@vps366782:/opt/tomcat/bin# curl -i nombritech.pl/.well-known/acme-challenge/haha
HTTP/1.1 302
Cache-Control: private
Expires: Thu, 01 Jan 1970 01:00:00 CET
Location: https://nombritech.pl/.well-known/acme-challenge/haha
Content-Length: 0
Date: Tue, 19 Dec 2017 02:34:39 GMT

And when I’m checking what is on this port it says that Tomcat… I don’t understand what is going on at all

@ahaw021 This is my last certificate that has already expired, thank you for the article I’m looking at it just now

I had no idea that it is so hard to configure it with only Tomcat aboard :frowning:

With tomcat properly configured you will need to use your original command:

sudo certbot certonly --webroot -w /opt/tomcat/webapps -d domain.pl -d www.domain.pl

Additionally, most examples use /opt/tomcat/webapps/ROOT as the webroot. Both should work but using the ROOT webapp makes sure tomcat doesn’t waste time spinning up a .well-known webapp.

Hey, thanks, I’ve just came up with the same idea and tried that:

root@vps366782:/opt/tomcat/bin# sudo certbot certonly --webroot -w /opt/tomcat/webapps -d nombritech.pl -d www.nombritech.pl --staging
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for nombritech.pl
http-01 challenge for www.nombritech.pl
Using the webroot path /opt/tomcat/webapps for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. nombritech.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://nombritech.pl/.well-known/acme-challenge/owdPQNAyRJPiWt7hE4HIWxQ4Oi9siZMgHOJdYlPbznA: Timeout

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: nombritech.pl
   Type:   connection
   Detail: Fetching
   http://nombritech.pl/.well-known/acme-challenge/owdPQNAyRJPiWt7hE4HIWxQ4Oi9siZMgHOJdYlPbznA:
   Timeout

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.

EDIT:

With ROOT like this?:

root@vps366782:/opt/tomcat/bin# sudo certbot certonly --webroot -w /opt/tomcat/webapps/ROOT -d nombritech.pl -d www.nombritech.pl --staging
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for nombritech.pl
http-01 challenge for www.nombritech.pl
Using the webroot path /opt/tomcat/webapps/ROOT for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. www.nombritech.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://www.nombritech.pl/.well-known/acme-challenge/Xd_JkF5-GC_bNFon9-6Ls1Ec8PCnX6V1CQrJduMB5YA: Timeout, nombritech.pl (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://nombritech.pl/.well-known/acme-challenge/49T3ia5rKl9GOtJU-3ioE1KTKVa1j2dNVg01fynZWPQ: Timeout

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: www.nombritech.pl
   Type:   connection
   Detail: Fetching
   http://www.nombritech.pl/.well-known/acme-challenge/Xd_JkF5-GC_bNFon9-6Ls1Ec8PCnX6V1CQrJduMB5YA:
   Timeout

   Domain: nombritech.pl
   Type:   connection
   Detail: Fetching
   http://nombritech.pl/.well-known/acme-challenge/49T3ia5rKl9GOtJU-3ioE1KTKVa1j2dNVg01fynZWPQ:
   Timeout

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.
root@vps366782:/opt/tomcat/bin#