19

I'm trying to configure Let's Encrypt certificates on a server that is publically accessible. Originally, the server was hiding behind a router, but I have since forwarded ports 80 and 443.

The certificate seems to have completed a majority of the install process, but fails with the message: Failed to connect to host for DVSNI challenge.

Full stack trace:

Updating letsencrypt and virtual environment dependencies......
    Requesting root privileges to run with virtualenv: sudo /bin/letsencrypt certonly --standalone -d example.net -d www.example.net
    Failed authorization procedure. example.net (tls-sni-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Failed to connect to host for DVSNI challenge

IMPORTANT NOTES:
 - The following 'urn:acme:error:connection' errors were reported by
   the server:

   Domains: example.net
   Error: The server could not connect to the client to verify the
   domain

Any support would be greatly appreciated!

I looked around elsewhere for a solution and haven't had much luck. Most other similar situations were resolved by forwarding port 443, but I am certain this port is already forwarded and open, albeit no service is currently running on it.

It shouldn't make a difference, but I'm trying to configure this certificate for use with Node JS on a Raspberry Pi.

James Taylor
  • 6,158
  • 8
  • 48
  • 74
  • I had across come with the same issue. I realized that after many times checking, the server 443 port can be accessed only by my IP. So, I recommend to check the accessing port 443 of the server, one more time. Good luck. – efkan Jan 08 '16 at 14:35

6 Answers6

12

I finally figured out what was going on. I discovered that the --manual flag steps through the authentication process interactively.

Each phase in the process will display a prompt similar to the following:

Make sure your web server displays the following content at
http://www.example.net/.well-known/acme-challenge/twJCKQm9SbPEapgHpyU5TdAR1ErRaiCyxEB5zhhw0w8 before continuing:

twJCKQm9SbPEapgHpyU5TdAR1ErRaiCyxEB5zhhw0w8.t7J7DDTbktMGCCu2KREoIHv1zwkvwGfJTAkJrnELb4U

If you don't have HTTP server configured, you can run the following
command on the target server (as root):

mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge
cd /tmp/letsencrypt/public_html
printf "%s" twJCKQm9SbPEapgHpyU5TdAR1ErRaiCyxEB5zhhw0w8.t7J7DDTbktMGCCu2KREoIHv1zwkvwGfJTAkJrnELb4U > .well-known/acme-challenge/twJCKQm9SbPEapgHpyU5TdAR1ErRaiCyxEB5zhhw0w8
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
"import BaseHTTPServer, SimpleHTTPServer; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()"

Press ENTER to continue

As I discovered, the process, despite being run as root itself, did not have the privileges to start the challenge server itself. Surely, this might be a bug in the API.

Running the script in the prompt directly produces the following error:

$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
> "import BaseHTTPServer, SimpleHTTPServer; \
> s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
> s.serve_forever()"

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
    self.server_bind()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
    SocketServer.TCPServer.server_bind(self)
  File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
    self.socket.bind(self.server_address)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 13] Permission denied

But running it as root (as the prompt itself stated) started the server correctly and could be monitored as the external server queried it to complete the challenge:

sudo $(command -v python2 || command -v python2.7 || command -v python2.6) -c "import BaseHTTPServer, SimpleHTTPServer; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()"

66.133.109.36 - - [08/Jan/2016 21:25:10] "GET /.well-known/acme-challenge/SZ88SorxBGXBtSZCTn4FX2g7u5XjnPFOOV3f5S5DuXB HTTP/1.1" 200 -
66.133.109.36 - - [08/Jan/2016 21:25:10] "GET /.well-known/acme-challenge/twJCKQm9SbPEapgHpyU5TdAR1ErRaiCyxEB5zhhw0w8 HTTP/1.1" 200 -

This error took awhile to diagnose as many things could have prevented the challenges from failing and the servers spawned were failing silently in the background.

James Taylor
  • 6,158
  • 8
  • 48
  • 74
8

If you're using Cloudflare DNS in front of your site, remember to have the DNS A, AAAA records point directly to your site, temporarily until renewal finishes.

Jeff Tsay
  • 458
  • 6
  • 7
  • 3
    **Cloudflare in my case too**. Disabling `DNS and HTTP proxy` (From `orange` to `grey` cloud) under `DNS` settings solved the issue. – Jasom Dotnet May 06 '16 at 13:16
2

I resolved this issue by disabling IPv6 on my Ubuntu 14.04 machine for Apache 2.4 as my server does not have a real IPv6 address. (Original post on https://community.letsencrypt.org/t/how-to-resolve-the-correct-zname-not-found-for-tls-sni-challenge-error-when-i-try-renew-certificate/9405/43)

To accomplish this, I explicitly set the IP address in /etc/apache2/ports.conf:

Listen <IP>:80
Listen <IP>:443

and in all vhosts:

<VirtualHost <IP>:80>

instead of:

<VirtualHost *:80>

After these changes, netstat -lnp | egrep ":443|:80" shows tcp in the first column instead of tcp6.

Then, the cerbot renew worked like a charm.

James Taylor
  • 6,158
  • 8
  • 48
  • 74
2

I fought this for several hours, complete with the same output in my logs. I even followed up on all the recommendations on this page. I only stumbled across my answer. I had pasted some code from another webconfig and it already had a <virtual host _._._._:443> section in it. After deleting that 443 section, the sudo certbot-auto --apache -d example.com ran without error and I had a working site.

I am drawing conclusions only from my experience: make sure you only have virtual hosts for port 80. Nowhere in the documentation that I read mentioned this issue, but it seems that certbot does not play nice with site-available conf file that already contains a 443 virtual host section.

wruckie
  • 1,717
  • 1
  • 23
  • 34
1

I suppose all of you already checked this. The same error raised to me during the renewal process. I had redirected the traffic from 443 to 8443 (with iptables). The solution was to remove the entry from iptables, stop the tomcat, then executing the renewal process worked like a charm. The script looks like this.

/etc/init.d/tomcat7 stop
iptables -t nat -D PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443

$letsencryptdir/letsencrypt-auto renew --standalone --standalone-supported-challenges tls-sni-01 --renew-by-default --email <my_email> --verbose --text  --agree-tos

iptables -t nat -I PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443
/etc/init.d/tomcat7 start
Carlos Cavero
  • 3,011
  • 5
  • 21
  • 41
0

I got the same error when tried:

./letsencrypt-auto --apache  -d example.com -d www.example.com

but it worked with:

./letsencrypt-auto certonly --webroot -w /var/www/html -d example.com -d www.example.com

After that you need to change cert paths in apache .conf file (default-ssl.conf) and restart apache.

user570605
  • 738
  • 7
  • 9