processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6.07k stars 1.51k forks source link

Can't get ejabberd to request letsencrypt certificate ACME module #3293

Closed buddudevelopers closed 3 years ago

buddudevelopers commented 4 years ago

Is your feature request related to a problem? Please describe. I tried to follow the guide to setup ejabberd ACME with ejabberd 20.01-1 on Ubuntu 20.04 LTS X64 on digitalocean cloud server but I keep getting the error Error: "Challenge failed for domain conference.fastmusawo.com: ACME server reported: Fetching http://conference.fastmusawo.com/.well-known/acme-challenge/WRvBWJWsSMXyI9X2UwKrvXWXl7NT77XmT1NABlB7mEo: Error getting validation data (error type: connection)" These are the steps I followed.

  1. I registered my domain fastmusawo.com
  2. I registered and setup a cheap ubuntu linux server (Ubuntu 20.04 LTS X64) droplet at digitalocean.com and logged in via putty SSH.
  3. I setup ejabberd apt install -y ejabberd
  4. I edited the file /etc/ejabberd/ejabberd.yml and added my domain to the hosts section
hosts:
  - localhost
  - fastmusawo.com

i added acme url to staging for testing

acme:
  ## Staging environment
  ca_url: https://acme-staging-v02.api.letsencrypt.org/directory
  ## Production environment (the default):
  # ca_url: https://acme-v02.api.letsencrypt.org/directory

I redirected traffic from port 80 to port 5280

sudo iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -i eth0 -p tcp --dport 5280 -j ACCEPT
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5280

I restarted ejabberd ejabberdctl restart I tried to request certificates for the domain I fully control ejabberdctl request_certificate all and i get the error

Error: "Challenge failed for domain conference.fastmusawo.com: ACME server reported: Fetching http://conference.fastmusawo.com/.well-known/acme-challenge/NIjL9YNBw8ta8Lqu5SXDn6FhjcGtDHgEpaekpNbgCGw: Error getting validation data (error type: connection)"

Describe the solution you'd like I want a guide to enable ejabberd request its own certificates

Describe alternatives you've considered using the native letsencrypt python client is an alternative but you have to manually grant ejabberd permission to the certificates

Additional context I am not sure whether it is a bug or I missed something. Anyone who has got this working should guide us. Thanks

treeshateorcs commented 4 years ago

Have you solved this?

badlop commented 4 years ago

You defined fastmusawo.com as one vhost for the XMPP server. If you have enabled mod_muc and other modules, there are other service hosts that ejabberd will request their certificates too. I imagine you will have something like in your log file:

2020-08-18 16:57:19.398543+02:00 [info]
 Requesting new certificate for fastmusawo.com, upload.fastmusawo.com
 and conference.fastmusawo.com from https://acme-v02.api.letsencrypt.org/directory

When doing those requests, it finds the problem that you noticed:

Fetching http://conference.fastmusawo.com/.well-known/
 acme-challenge/NIjL9YNBw8ta8Lqu5SXDn6FhjcGtDHgEpaekpNbgCGw:
 Error getting validation data (error type: connection)"

I have limited ACME knowledge, but this apparently means that a connection to conference.fastmysawo.com is attempted, but can't be established.

buddudevelopers commented 4 years ago

@badlop I just need to know this... Does your own ejabberd server successfully request for its own certificates? If so, please share how you set this up. Currently I manually request for the certificates and set them in the config file. It seems the acme module was designed to automate this but I failed to get it working. Maybe one day I will fix it, when my erlang knowledge gets better

adriangibanelbtactic commented 4 years ago

The 20.04-1~bpo10+1 package from Debian buster backports has the following default 5280 stanza:

 -
    port: 5280
    ip: "::"
    module: ejabberd_http
    tls: true
    protocol_options: 'TLS_OPTIONS'
    request_handlers:
      /admin: ejabberd_web_admin
      /.well-known/acme-challenge: ejabberd_acme

.

The default package ejabberd.yml might be a similar to the Debian stanza where tls is turned on.

The problem here is that 5280 port is setup to listen as an https server and not as a http server.

Letsencrypt validation server expect a http connection on port 80 and finds an https connection on port 80 and that's why it fails.

The ejabberd_20.07-0_amd64.deb package from official ejabberd site has a valid value for 5280 stanza:

  -
    port: 5280
    ip: "::"
    module: ejabberd_http
    request_handlers:
      "/admin": ejabberd_web_admin

@buddudevelopers, If this is your exact problem can you please open a bug to Debian/Ubuntu packagers?

Thank you.

adriangibanelbtactic commented 4 years ago

I also want to comment that the default ejabberd stanza would enable /admin to be accesible from a non secure port.

So my workaround is to leave the default (as per Ubuntu/Debian package) 5280 stanza as:

 -
    port: 5280
    ip: "::"
    module: ejabberd_http
    tls: true
    protocol_options: 'TLS_OPTIONS'
    request_handlers:
      /admin: ejabberd_web_admin
      /.well-known/acme-challenge: ejabberd_acme

and add a new one that only handles the Letsencrypt renewal on port 5380 (Yes, a random port, I have used).

  -
    port: 5380
    ip: "::"
    module: ejabberd_http
    tls: false
    request_handlers:
      /.well-known/acme-challenge: ejabberd_acme

Now you can redirect 80 port to 5380 port and you are ready to use the auto acme renewal.

I might open a new bug for this RFE.

Neustradamus commented 3 years ago

@prefiks, @badlop: What do you think?

badlop commented 3 years ago

Is there anything to do regarding this ticket? What is exactly the problem right now? Otherwise, it should be closed.

adriangibanelbtactic commented 3 years ago

Is there anything to do regarding this ticket? What is exactly the problem right now? Otherwise, it should be closed.

My recommendation is to add:

  -
    port: 5380
    ip: "::"
    module: ejabberd_http
    tls: false
    request_handlers:
      /.well-known/acme-challenge: ejabberd_acme

to default ejabberd.yml and update documentation accordingly so that external 80 port is redirected to internal 5380 so that LetsEncrypt can be performed without exposing /admin in an insecure port.

After that it's recommended to open a bug against the Debian/Ubuntu (not from Ejabberd but from Debian/Ubuntu themselves) packages so that their default ejabberd.yml also has this external stanza.

Note: The original bug is probably a consequence of Debian/Ubuntu packages serving the 5280 port (which should be non-secure) as a secure port (https) which it's not how the Ejabberd repo package is serving the 5280 port.

Note: Feel free to choose an alternate port to 5380 or another workaround.

badlop commented 3 years ago

Let's recapitulate. In general:

So, I guess it makes sense that, if ejabberd XMPP server provides a HTTP service, it's by default in port 5280. And, when offering a HTTPS service, one possible port number that can be expected is 5443.

And that's what ejabberd.yml.example shows since some time ago.

Other XMPP servers with HTTP service:

Then, returning to ejabberd: I see the Debian package enabled tls for port 5280 a year ago: https://salsa.debian.org/ejabberd-packaging-team/ejabberd/-/commit/33aa9596e91c67680f7e38d3471ceba0973b49f7

So, the first thing to do should be consult the Debian packagers to know the reason for that change: is the reason specific to Debian, or is it a general reason that we should all adopt?

Neustradamus commented 3 years ago

@debalance: Can you look it and update the debian conf?

debalance commented 3 years ago

@Neustradamus 5280 has been the default port to access ejabberd's web interface since more or less forever. As soon as it became easily possible I switched the webinterface from HTTP to HTTPS completely. Since HTTP was not offered at all any longer, I decided to go the conservative route and stick with the well known port to keep everybody's life as undisturbed as possible. I see no reason to change anything.

ACME came much later, if you do not want it to use the same port as the web interface, configure it to a different one as suggested by others here. You could even use 8443 since the web interface does not occupy that one.

Neustradamus commented 3 years ago

@debalance: I think that the best solution is:

debalance commented 3 years ago

@debalance: I think that the best solution is:

* To remove TLS from 5280 to have only acme and temporary HTTP

* Use HTTPS only with 5443

Have you read my previous explanations? I will not do that. I can place the ACME stuff on a separate port without TLS in the default config if you like, nothing else.

badlop commented 3 years ago

Thanks for your explanations!

In summary, after checking all the points mentioned in this thread, I consider impossible to provide one single default configuration that satisfies all the requirements, as they are conflicting:

I suspect, for every change done, somebody will find a good reason to complain. So, /me won't change anything.

Instead, I prefer to improve the ejabberd documentation, so it's useful and guides the administrator regardless of the installation method, its default configuration, or its current configuration. To start this: https://github.com/processone/docs.ejabberd.im/commit/8deb6490231a323bd948896d3ebcbf8c9af7a8ea

mtangoo commented 3 months ago

Here is what I did with Apache2.x which fowards the traffic without any modification. mod_proxy must be enabled

the base URL is chats.example.com

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyRequests Off

    ServerAdmin help@example.com
    ServerName chats.example.com
    ServerAlias www.chats.example.com conference.chats.example.com www.conference.chats.example.com proxy.chats.example.com www.proxy.chats.example.com pubsub.chats.example.com www.pubsub.chats.example.com upload.chats.example.com www.upload.chats.example.com

    ProxyPass / http://localhost:5280/
    ProxyPassReverse / http://localhost:5280/    
</VirtualHost>