Getting a SSL certificate from Let’s Encrypt

Using Certbot from the CLI.

Installing certbot

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot

Obtaining a certificate

Starting certbot is next:

certbot certonly --webroot -w /var/www/wp_0x002a.net -d 0x002a.net

The website tells me, that my server architecture (Ubuntu 17.04) does not provide automated installation. It worked after some configuration changes for nginx (the challenge is written into a hidden directory within the webroot) in /etc/nginx/global/common.conf:

location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/wp_0x002a.net;
}

location = /.well-known/acme-challenge/ {
    return 404;
}

It was a good idea to create a simple textfile within this directory and trying to access it via the browser.

Configuring ngnix to use the certificate

file /etc/nginx/snippets/ssl-0x002a.net.conf:

ssl_certificate /etc/letsencrypt/live/0x002a.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/0x002a.net/privkey.pem;
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

File /etc/nginx/snippets/ssl-params.conf:

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# disable HSTS header for now
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Resources

My very own mail server (exim4)

Installing (apt-get install exim4) and configuring (dpkg-reconfigure exim4-config) the server. I decided not to split the configuration into multiple files within the /etc/exim4/conf.d directory, so the single config file /etc/exim4/exim4.conf.template is used instead! The default configuration seems to listen on port 25 only. Adding the lines

daemon_smtp_ports = 25 : 465 : 587
tls_on_connect_ports = 465

enables the TCP ports 465 and 587 as well, some mail programs need it this way.

In a subsequent step, the mail server is configured for TLS. A self signed certificate is generated by executing /usr/share/doc/exim4-base/examples/exim-gencert. MAIN_TLS_ENABLE = yes in the TLS section of /etc/exim4/exim4.conf.template enables it. In the same file, the sections with plain_saslauthd_server and login_saslauthd_server need to be uncommented.

Allowed email users are added to exim4 using /usr/share/doc/exim4-base/examples/exim-adduser. The password file /etc/exmin4/passwd should be protected: chown root:Debian-exim /etc/exim4/passwdfollowed by chmod 640 /etc/exim4/passwd. For each of these users a home directory is needed to deliver the mail (calling adduser <name> on Ubuntu).

Configuring SASL by installing it (apt-get install sasl2-bin) and editing START=yes in /etc/default/saslauthd. Finally, exim4 needs to be a member in the sail group: adduser Debian-exim sasl. The server needs a restart: systemctl restart saslauthd.

At the end, updating (update-exim4.conf) and restarting (systemctl restart exim4) might be a good idea. The update converts the config template and auto-generates the configuration to /var/lib/exim4/config.autogenerated where it is read by exim4 itself.

For exim4 to work, the firewall should open TCP ports 25 and 587 (SSL).

Continue reading “My very own mail server (exim4)”

Creating a firewall (iptables)

Make sure that iptables are installed (otherwise call apt-get install iptables). A very basic rule set that allows http, https, and ssh (via default port 22) access:

*filter

# Define default policies
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT

# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Allows HTTP and HTTPS connections from anywhere
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allows SSH connections 
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow DNS lookups
-A INPUT -p udp --sport 53 -j ACCEPT
-A INPUT -p tcp --sport 53 -j ACCEPT

# Allow NTP
-A INPUT -p udp --sport 123 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

COMMIT

Installing these rules – according to wiki.debian.org:

iptables-restore < /etc/iptables.test.rules
iptables -L # Are these my rules?
iptables-save > /etc/iptables.up.rules

Activating iptable rules at boot time requires a file /etc/network/if-pre-up.d/iptables (as a shell script, it requires x permissions):

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules

Nowadays, the same is needed for IPv6 with some minor changes because ICMP plays a far more important role in this version:

 *filter

-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT

# -A INPUT -m rt --rt-type 0 --rt-segsleft 0 -j DROP
# -A FORWARD -m rt --rt-type 0 --rt-segsleft 0 -j DROP
# -A OUTPUT -m rt --rt-type 0 --rt-segsleft 0 -j DROP

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

-A INPUT -p ipv6-icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -m state --state NEW -m udp -p udp --dport 546 -d fe80::/64 -j ACCEPT

-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

# -A INPUT -j REJECT --reject-with icmp6-port-unreachable
# -A FORWARD -j REJECT --reject-with icmp6-port-unreachable

COMMIT

Enabling these rules goes the same way as with IPv4 with the sole exception that ip6tables, iptables-restore and ip6tables-save must be called.