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/ -d

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/;

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_certificate /etc/letsencrypt/live/;
ssl_certificate_key /etc/letsencrypt/live/;
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

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

# from
# and

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 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;


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)”


There were too many attacks against the sshd (thousands on a single day), so I decided to install fail2ban. Installation is a simple apt-get install fail2ban. Next, a copy of the file /etc/fail2ban/jail.conf with the name jail.local is created. A possible configuration could be:

before = paths-debian.conf

ignoreip = # more networks if needed
bantime  = 86400
findtime  = 3600
maxretry = 3
backend = auto
usedns = warn
logencoding = auto
enabled = false

enable  = true
port    = ssh
filter  = sshd
logpath = /var/log/auth.log
backend = %(sshd_backend)s

This configurations bans an attacking ip address, if there are more than 3 failed login requests within an hour (findtime = 3600). The attacker is banned for 24 hours (bantime = 86400).

Continue reading “fail2ban”

Dissecting a build.gradle file

As a reference, the following parts form a build.gradle file for a simple Java project:

group 'org.asysob'
version '1.0'

The organisational identifier for the project and the current version.

buildscript {
    repositories {
    dependencies {
        classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-M3'
        classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0'

Continue reading “Dissecting a build.gradle file”

Java example using GSON, 0MQ and built with Gradle

Just implemented a little Java program where a publisher sends JSON encoded messages that are received by a subscriber. The messages contain simple integers and are tagged as even or odd. PUB/SUB is done with the pure Java 0MQ implementation jeromq while the GSON library makes JSON encoding easy. Gradle is my favourite build tool, so this version of the file may serve as a starting point for future projects. JUnit5 and the shadow plugin for Uberjars are already configured; although the first is not used in this project.

Moving my wordpress blog to https

I received a SSL certificate for this blog. Switching from http to https is more work than expected, but fortunately, with the help of some tools, it is just a matter of minutes.

The easiest part: Change the URL scheme of the blog address in Settings -> General tab to HTTPS.

The next step is, to enforce HTTPS by advising the www server to redirect every query. On the blog, i found the required nginx configuration:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;

Thanks to a blog entry (, i became aware of the problem that any entries with HTTP already stored in the database must be changed as well. Fortunately, with the help of the wordpress plugin Better Search Replace this is a matter of a few minutes. Since we make detailed changes in the database itself, a backup if it is definitely a good idea. After installing and activating, the plugin is accessible via Tools. It seems to be important, to replace GUIDs as well, so this checkbox should be selected. The job is done by entering the old address and the new address, by selecting all relations in the database, and finally by starting the task. A dry run can be selected first.

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:


# Define default policies

# 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 -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


Installing these rules – according to

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):

/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:



# -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 -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


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

A pair of keys for ssh

ssh-keygengenerates the key pair (private key keyname and public key The easiest but somewhat more dangerous way is to use passphrase-less keys. Keys may be hardened against brute force attacks by increasing the number of rounds (-a 128) and by making the keys longer (-t rsa -b 4096). Don’t forget to add a comment -C "comment" to the public key which makes it easier to be recognized:

ssh-keygen -a 128 -t rsa -b 4096 -C "comment" -f "keyname"

The private key is needed on any host used as a source for logging in. Any target system needs a .ssh subdirectory in the home of the user allowed to login remotely with rwx permissions for the owner (chmod 700). A file called authorized_keys is needed which holds the public keys of all remote hosts from where a login happens (rw permissions for owner (chmod 600) and make sure that the owner actually owns this file). The public key can be appended by using cator it can be copied from a remote machine using ssh-copy-id -i @. ssh-copy-id works with localhost in case the keys are generated on the target machine.