neurobin / letsacme

A tiny script to issue and renew TLS/SSL certificate from Let's Encrypt
https://neurobin.org/projects/softwares/unix/letsacme
MIT License
26 stars 9 forks source link

Subdomains: Error requesting challenges #6

Open fotolab opened 6 years ago

fotolab commented 6 years ago

Hi! Thank you for your tutorial. I followed all steps. It worked for my main domain! Thank you! but I have troubles with my subdomains.

I was using your method described in 3.3 by using a challenge subdomain and redirecting all the acme-challenge traffic to my new challenge subdomain via htaccess. After some troubleshooting I was able to have a fully functional automated CRON Job for renewing my SSL certificate on my example.com website.

While its working with my naked domain, However, I get an Error during the process for my subdomain (the www. version). I have to note, that Im on a shared hosting provider. In order to fix the problem, I tried out to create a json in the letsacme folder saying that my global acme-dir would be my challenge/challenge directory. I was using the suggested piece of code in the description. The problem persits tough.

It looks like this. In my letsacme.log it says:

Logs for letsacme script

Parsing account key... Parsed! Parsing CSR... CN: example.com\x0D Parsed! Registering account... Already registered! Verifying example.com ,DNS:www.example.com

E: Error requesting challenges: 400 <bound method _fileobject.read of <socket._fileobject object at 0x234e850>>

I know it looks similar to this issue: https://github.com/neurobin/letsacme/issues/1 But I have no shell access, the script generally works but only not for my subdomains. plus it seems to fail at an earlier stage (requesting challenges). So unfortunately, the solution for the other issue does not seem to help me. But its interesting that i share the fact, that there appears to be a 400 Error (whatever that means in my case).

I made sure that:

The problem is not only affecting the www. version, but every other subdomain (including mail.example.com). I came to a point where I need help in order to fix this problem. I looking forward to hear from you.

Greetings

fotolab commented 6 years ago

Im also curious if your script (and tutorial) will adapt to the wildcard ssl certificates, that Lets encrypt will offer from january '18 on. Maybe there is a way to automate the DNS challenge as well?

neurobin commented 6 years ago

I can't talk about the DNS challenge right now, but yes, I will try to adapt to the wildcard when it's available.

neurobin commented 6 years ago

Problem: CN: example.com\x0D it should be CN: example.com

How did you create the CSR?

fotolab commented 6 years ago

Thank you for your quick answer. ( Also for the info on wildcard ;-) )

Now I'm going to go through the process live and describe step by step how I create the CSR:

  1. Im on Windows 10, so I use the Linux-Bash Add for commands
  2. I create a dom.list file containing
example.com
www.example.com
mail.example.com
www.mail.example.com
  1. I make sure the gencsr.config file is prepared and in the working directory
  2. I use the gencsr file code

At first I did not recognize the "/x0D" extension in the log file and the CN. Now I can say, it happens also when I create new dom.key, dom.list and dom.csr files. By the way, /x0D seems to be a sign for the "CarriageReturn". I edited the .list file with notebook++ and there I need to use carriage returns in order to write into a new line. Im not sure if that may be the problem, but I will look for an alternative way of creating .list files.

neurobin commented 6 years ago

use notepad++ or geany, the carriage return is definitely a problem. Please use dos2unix to convert the files to unix format to make sure everything works as expected.

dos2unix dom.list
dos2unix gencsr.conf
#then create the csr again
./gencsr
fotolab commented 6 years ago

Thank you again for your answer. I will try that out soon. Since I have some troubles with installing dos2unix on my bash now, i will have to fix that at first. That might take a while. But when I managed to do so, I will give you an update.

fotolab commented 6 years ago

Luckily, I solved bash's internet connectivity issue by simply adding a google name server (8.8.8.8) in it's resolve.conf nano /etc/resolve.conf, and by closing down my firewall for a moment. Then I updated the whole thing apt-get update, and installed unix2dos apt install dos2unix. Afterwards, I followed your instructions and converted the gencsr.conf, and the dom.list file successfully to a unix format. Also creating new .key and .csr files worked well.

When I ran the cron-job, I was very surprised when I looked into the log file. First of all, the "/x0D" extension was gone! A quick "Yeay!" for having solved that problem.

However, I have another problem now. In the log it said that challenge files have been written, but the files were not downloaded successfully. It felt like I was suddenly catapulted back a thousand steps. Suddenly, I was not able to get any certificate, not even for example.com (which has been working fine before). That was so surprising to me, because the only thing that I changed since two weeks was using the new .key and .csr files. Everything else stayed exactly the same. Weird. Why did my original workaround quit working? I don't know.

Then I tested something. Basically, the whole certification process still works. I am able to get a certificate for example.com, by using the classic "/.well-known/acme-challenge" directory as acme-dir. But only when I am not using the "challenge.example.com" subdomain-workaround. This is, however, not a solution for me. Because this strategy still produces (As expected) issues regarding my subdomains (see the quoted log file).

Logs for letsacme script

Parsing account key... Parsed! Parsing CSR... CN: example.com Parsed! Registering account... Already registered! Verifying example.com... Well known path was parsed: .well-known/acme-challenge verified! Verifying www.example.com... Traceback (most recent call last): File "/home/user/letsacme/letsacme.py", line 492, in main(sys.argv[1:]) File "/home/user/letsacme/letsacme.py", line 477, in main CA=args.ca, force=args.force) File "/home/user/letsacme/letsacme.py", line 317, in get_crt resp = urlopen(wellknown_url) File "/usr/lib64/python2.7/urllib2.py", line 154, in urlopen return opener.open(url, data, timeout) File "/usr/lib64/python2.7/urllib2.py", line 437, in open response = meth(req, response) File "/usr/lib64/python2.7/urllib2.py", line 550, in http_response 'http', request, response, code, msg, hdrs) File "/usr/lib64/python2.7/urllib2.py", line 469, in error result = self._call_chain(args) File "/usr/lib64/python2.7/urllib2.py", line 409, in _call_chain result = func(args) File "/usr/lib64/python2.7/urllib2.py", line 656, in http_error_302 return self.parent.open(new, timeout=req.timeout) File "/usr/lib64/python2.7/urllib2.py", line 431, in open response = self._open(req, data) File "/usr/lib64/python2.7/urllib2.py", line 449, in _open '_open', req) File "/usr/lib64/python2.7/urllib2.py", line 409, in _call_chain result = func(*args) File "/usr/lib64/python2.7/urllib2.py", line 1258, in https_open context=self._context, check_hostname=self._check_hostname) File "/usr/lib64/python2.7/urllib2.py", line 1211, in do_open h.request(req.get_method(), req.get_selector(), req.data, headers) File "/usr/lib64/python2.7/httplib.py", line 1017, in request self._send_request(method, url, body, headers) File "/usr/lib64/python2.7/httplib.py", line 1051, in _send_request self.endheaders(body) File "/usr/lib64/python2.7/httplib.py", line 1013, in endheaders self._send_output(message_body) File "/usr/lib64/python2.7/httplib.py", line 864, in _send_output self.send(msg) File "/usr/lib64/python2.7/httplib.py", line 826, in send self.connect() File "/usr/lib64/python2.7/httplib.py", line 1236, in connect server_hostname=sni_hostname) File "/usr/lib64/python2.7/ssl.py", line 350, in wrap_socket _context=self) File "/usr/lib64/python2.7/ssl.py", line 611, in init self.do_handshake() File "/usr/lib64/python2.7/ssl.py", line 841, in do_handshake match_hostname(self.getpeercert(), self.server_hostname) File "/usr/lib64/python2.7/ssl.py", line 273, in match_hostname % (hostname, dnsnames[0])) ssl.CertificateError: hostname 'www.example.com' doesn't match 'example.com'

I am going to set up another clean workaround soon. Until then, if you see some other "core problems" (like the one with the carriage-return; shame on me), let me know.

Greetings!

neurobin commented 6 years ago

your challenge.example.com is in http, right? it must not redirect to https version ...

fotolab commented 6 years ago

Good Point! Guess what, you're right again. SSL certificates and redirections were likely involved in the reported crash of my previously working workaround setup. I collected two plausible causes. First, I discovered, that the wordpress plugin "W3 Total Cache" (W3TC) is using the .htaccess file, in order to make the caching process work. By default, the plugin is recognizing ssl-pages and therefore introduces a ssl-redirection into the .htaccess file (other caching plugins do that as well). Basically, W3TC is inserting a block of code <IfModule mod_rewrite.c> [...] </IfModule> with the redirection stuff it needs. I suppose that W3TC might have updated the .htaccess file on its own, leading to a https redirection of the requests to my challenge.example.com. Second, I found that there is a default "AUTO SSL" script running in cpanel, that may have installed a self signed certificate on my challenge.example.org when I was not looking.

I am very happy to say, that I managed to install SSL-certificates on multiple subdomains now. Feels like a christmas present. Yihaaaa! (Thank you so much for your advices, your tutorials, your wisdom). This is what I did to solve it:

1. I manually deinstalled the SSL certificate on challenge.example.com (again..). 2. I disabled the auto-SSL function on challenge.example.com. 3. I restructured my .htaccess file. Instead of using only one <IfModule mod_rewrite.c> [...] </IfModule> block, Im using multiple blocks now. It looks like this:

<IfModule mod_rewrite.c> RewriteEngine On RewriteBase "/" RewriteRule ^.well-known/acme-challenge/(.*)$ http://challenge.example.com/challenge/$1 [L,R=302] </IfModule>

<IfModule mod_rewrite.c> STUFF from the W3TC Plugin....... </IfModule>

<IfModule mod_rewrite.c> RewriteCond %{HTTPS} =off RewriteCond %{HTTP_HOST} !=challenge.example.com RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </IfModule>

4. I also inserted the proper workaround challenge/challenge directory into the .json file and into the renewcert file again.

Now I have SSL-certificates on:

example.com www.example.com mail.example.com

However, Im stuck again :D The certification process still fails, when I try to certificate the following subdomains:

webmail.example.com webdisk.example.com cpanel.example.com autodiscover.example.com

The Log says for example:

ssl.CertificateError: hostname 'webmail.example.com' doesn't match either of 'example.com', 'mail.example.com', 'www.example.com'

I think I am not able to certificate those last four domains, because it's my hosting provider who has the proper control over them. Is there any way, in which I can still add them into the certificate?

neurobin commented 6 years ago

Seems like your CSR does not include those subdomains. Recreating the CSR including those subdomains may help