I’m not a recipe blog with a large intro before telling you the fix. I’ll describe the problem and the steps later. I’m here to help, because I’m nice and my time is your time.
Possible solution:
sudo nano /etc/letsencrypt/options-ssl-apache.conf#add “ALL:” to the start of cipher lists and ctrl-X then yessudo systemctl restart apache2
Problem: No matter what you do, Alexa (even in the test function) is unable to contact your intent endpoint and says “Unable to reach the requested skill” no matter how reachable the host.
- You have a valid SSL cert (if you don’t, get one, or upload your /etc/letsencrypt/live/{domainname}/fullchain.pem file to the “self-signed x509” dropdown on the endpoint). You will likely still get the error.
- You have debugged, sent your own non-alexa-verified JSON, etc. Code all works. Your backend isn’t the problem (hopefully. Minr is python running in apache2 under WSGI and a mixed bag of old libs under a virtual environment, making debugging even more difficult).
- You pass sslchecker.com, you are sure your SSL isn’t the problem and it has to be something ridiculous happening. (Please use sslchecker, to make sure that your cert really is set up right and you have the proper SAN name included for your domain, that could be the problem).
All of that is fine and you are sure that you are going insane (a rare few will ever understand how nearly mad I went hunting down why two servers couldn’t even send a message! Tracking this down was like hunting an invisible unicorn hiding in a sock drawer that no longer opens). I can assure you, Amazon is the problem and so is your SSL. “But I checked my SSL!”. You checked your certificate, which is right by now. I promise, the problem is your SSL. Well, the problem is Amazon’s SSL. (You’re welcome. They won’t help you with that.) It takes two sides to make a handshake.
So, let’s say you hate lambda (because it’s unnecessary in certain situations. I have an app/server/whatever, why would I use lambda? I write my own code and have my own hardware). You WILL run into this if you host your own endpoint for Alexa and use letsencrypt/apache. I am really surprised I didn’t find this solution online. It brought me out of blogging retirement to post because this is dumb and no one seemed to know the answer. Hopefully, with all my typing, I’ve hit enough keywords to get you here!
If you are using letsencrypt (let’s encrypt, Certbot) and apache (apache2) or pretty much any other ssl enabled server. You might have encountered the error “unable to reach the requested skill” on whatever backend you are using for your Alexa skill endpoint (assuming it’s not Lambda). If that is the case, the issue is possibly the cipher suite on your SSL connection. You are probably not even receiving the request. Yes, I did a lot of logging to look for the request. I was never getting it. It never hit my app, why? because Alexa bailed before it sent it. SSL is a painful process, especially when Amazon offers no real error explanation.
What happened? The Alexa skill tried to make a connection to your endpoint. It didn’t send a request yet, it just asked if it could. It said “Hey, do you exist?”. Your server said “Yes”. Then it said “What language can we speak”. Your server said “A safe one” and Alexa said “I don’t know any of those” and bailed. This sounds ridiculous, but it is exactly what happened to me. Amazon needs to play catchup and fast.
When you have SSL enabled there’s a couple ways the computers can talk. They have the method of transmission (ssl1,2,3/tls 1/1.1/1.2/1.3, etc) and the cipher (encryption) between them. Your server decides how it can talk, Amazon decides how Alexa can talk. If you have a modern server security scheme, Alexa CAN’T TALK TO IT BECAUSE THEY ARE BEHIND AND DON’T LIKE SECURITY!!! (I’m a little bitter). Alexa forces TLS 1.2, which is okay. That’s safe. But it then asks for the cipher and if it doesn’t find a match with your server you get the “Unable to reach the requested skill” error. No more debugging. No answer to why it failed. “Is my server offline?” maybe. “Is it broken?” maybe. “Is Alexa garbage?” definitely. But the problem could be that it couldn’t establish a connection, despite your perfectly valid SSL certificate and installation, because it didn’t agree on a handshake cipher protocol.
Why did this happen? Because letsencrypt (and other cert suppliers, but that’s mine) have decided to remove the insecure ciphers by default and AMAZON and ALEXA ONLY USE BROKEN CIPHERS! So, if your server is using the latest security, it will be basically UNREACHABLE by the Alexa skill because it will only try to connect by broken and insecure CBC (blockchain) and SHA (completely destroyed encryption) ciphers.
How can you fix this after probably hours of reinstalling your cert and testing all the things in the world? Just allow all ciphers. Is this secure? No. It absolutely is not. Is it better than HTTP? yes. Can I find a cipher that amazon and I can agree on so that I only enable one and not all? Probably, but I didn’t, so I just enabled them all. Here’s what you do. If you are using letsencrypt and apache2 (with python WSGI or a node.js module or php or any backend really that runs through apache) and have used Certbot, you have a file /etc/letsencrypt/options-ssl-apache.conf that is being “included” in every vhost, if you let Certbot do its normal thing. This file looks like this as of 2021-03-11:
If you make the simple change of adding “ALL:” at the front of the SSLCipherSuite line, to allow all ciphers, and then of course restart apache or whatever host you are using, Alexa will finish the handshake. (to restart apache2 type “sudo systemctl restart apache2”)
Is this the best solution? No. Absolutely not. This will downgrade you from an A to a B security. Is it still secure? yes, probably more so than most websites. What is better? finding a single cipher that you and Amazon can agree on. What is best? Having Amazon UPDATE THEIR CIPHER REQUIREMENTS TO USE SOMETHING THAT ISN’T KNOWN TO BE EXPLOITABLE. There is no overlap between non-exploited ciphers and their acceptable handshake list. None. Zero. Nada. They only accept ciphers that are known broken. Why? Beats me. Lazy? Useless? Clueless? Maybe if they paid their engineers, things would work right.
Anyway, rant aside. I hope this helped. You lowered the security of your endpoint because Jeff Bezos doesn’t want to pay competent security engineers. I hope I helped.
Bingo, Kevin. Thanks for the fix–it worked for me. Thankfully, I only spent an afternoon pulling my hair out before I stumbled across your post. Hard to believe that Amazon can’t negotiate a robust set of ciphers. AWS lambda’s generate more revenue for them, privately-hosted web services do not. You don’t think….nah.