Category: bsd

  • On servers timezone and tmux

    A while ago I was fighting with a timezone set on a server because of the daylight saving time kicked in: during the ghost hour I had troubles with finding automated jobs. Moreover, the server was located overseas and depending on when I was checking the remote date and time, I could get a different time delta.

    Then, the quasi-philosophical question about “which timezone should be set for a remote server: my timezone or local timezone to the server?” has began rolling in my mind.

    After some research, I found a piece of technical advice from Yeller. In short, their advice can be summarized with:

    Use UTC
    Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC. Use UTC.

    (no, really check the linked post: it is full of good and agreeable technical points to use UTC).

    After setting the default timezone for all my servers to UTC, there are some tweaks to live happily ever after with UTC.

    First, add your timezone and export it into the TZ variable:

    echo 'export TZ=/usr/share/zoneinfo/Europe/Rome' >> ~/.zshrc

    This brings a notable advantages:

    • without TZ set:

    % date
    Mon Mar 25 20:56:43 2019
    journalctl -f
    [...]
    Mar 25 20:57:51 golf systemd-logind[1154]: Session 980 logged out. Waiting for processes to exit.

    • with TZ set you get every message* localized in the selected timezone:

    % date
    Mon Mar 25 21:57:53 CET 2019
    journalctl -f
    [...]
    Mar 25 21:57:51 golf systemd-logind[1154]: Session 980 logged out. Waiting for processes to exit.

    * = every message from a sane and decently written program that knows about timezones and honors the TZ variable.

    Secondly, I usually have everything running in a tmux session with the time in the tab bar. After changing the server timezone to UTC, tmux was outputting the time in UTC: I wanted to show my local time as well. In order to show localized time, you have to change some parameters:

    • Output the time and the timezone in the tab bar:

    In ~/.tmux.conf:
    set -g status-right '%a %b %d %H:%M %Z'

    • Make sure to send your TZ variable whenever you are using SSH:

    In ~/.ssh/config:
    Host *
    [...]
    SendEnv TZ

    • Make sure that your SSH server automatically accepts the TZ variable:

    In /etc/ssh/sshd_config
    AcceptEnv [...] TZ

    Restart your sshd service and try to login in the remote server. Your tmux tab bar should show the updated time in your localized timezone, while still using UTC as the global timezone for the server.

  • Secure your SSH server against brute-force attacks with Fail2ban

    The problem: SSH can be brute-forced

    I usually leave an SSH server on a dedicated port on every server I administer and, as you may recall, I even linked two well-written guides to properly configure and harden SSH services.

    Now, Internet is a notoriously bad place: scanners and exploiters have always been there, but brute-forcers are on the rise and SSH is one of the services that is heavily targeted by them. Let’s gather some data:

    quebec:/var/log # ag "Invalid user" auth.log.2 auth.log.3 | wc -l
    4560
    quebec:/var/log # head -n 1 auth.log.3 | cut -d " " -f 1-3
    May  8 07:39:01
    quebec:/var/log # tail -n 1 auth.log.2 | cut -d " " -f 1-3
    May 21 07:39:01
    

    So, even if my SSH is allowing only PubkeyAuthentication, in the timespan of two weeks there has been 4560 brute-force attemps (~325 attempts per day).

    This is annoying and potentially insecure, depending on your configuration. What can we do?

    The solution: using Fail2ban

    I have recently read some posts about this problem, and luckily (for us) there are multiple solutions to this problem: the most popular one is Fail2ban. To cut a long story short, the idea behind Fail2ban is to monitor log files of the monitored services and keep track of which IP addresses are trying to use a brute-force attack to use the service. If the same IP address causes a number of bad events in the specified time frame, Fail2ban bans that IP (using netfilter/iptables) for a configure d time amount.

    So I just need to install Fail2ban and I am ready to go:

    # zypper in fail2ban
    

    NO. NO. NO. You will not be protected against brute-force attacks if you just install it without configuring it.

    You MUST configure it!

    Let’s take a step back. The core of Fail2ban is the configuration:

    # "bantime" is the number of seconds that a host is banned.
    bantime  = 600
    
    # A host is banned if it has generated "maxretry" during the last "findtime"
    # seconds.
    findtime = 600
    maxretry = 5
    

    These are the default values. And brute-forcers know them, so they can time accordingly their attempts not to break these limits (or to begin again their attempts after the bantime). Again, let’s gather some data. I noticed a frequent brute-forcer IP and follow his data:

    quebec:/var/log # ag "Invalid user" auth.log.2 auth.log.3 | ag <IP> | cut -d " " -f 1-3
    
    auth.log.2:8106:May 21 03:34:22
    auth.log.2:8112:May 21 03:43:41
    auth.log.2:8116:May 21 03:53:00
    auth.log.2:8120:May 21 04:02:18
    auth.log.2:8126:May 21 04:11:47
    auth.log.2:8132:May 21 04:21:08
    

    Can you believe it? It was just on the edge of the 600 seconds between every attempt!

    Key concept: outsmarting brute-forcers

    The key concept here is to provision a personalized version of your specific choosing of these values, in order to outsmart the brute-forcers (which is easily done). In order to do so, do not modify Fail2ban’s default config file (/etc/fail2ban/fail2ban.conf) but rather just override the defaults in another config file that you can create with:

    quebec:/etc/jail2ban # awk '{ printf "# "; print; }' /etc/fail2ban/jail.conf | sudo tee /etc/fail2ban/jail.local
    

    Your customizations have to be defined in /etc/fail2ban/jail.local, so your selected bantime, findtime and maxretry must go there.

    Further customization

    Some useful findings:

    • you can selectively whitelist a group of IPs, hosts, subnets, etc. in order to not being banned when accessing services from whitelisted IPs (e.g. ignoreip = <VPN subnet>/8 <another VPN subnet>/16)
    • you can receive an email everytime someone is banned with their whois (with good relief from the system administrator)
    • if you are using WordPress, you can extend Fail2ban to monitor failed WordPress login attempts with a WordPress plugin (did I mention that Fail2ban not only monitors sshd? It also monitors nginx, apache, vsftpd and other services)
    • you can have Fail2ban automatically sends the banned IPs to a shared blacklist (I have never used this)

    Disadvantages

    Everything seems perfect now, but what are the disadvantages of it? Given that Fail2ban reasons in terms of banning single IPs, it cannot protect you against distributed brute-force attacks. In this case Fail2ban is pretty useless and other solutions should be implemented that depends from case to case.

  • SQLite3, NFS e FreeBSD: risolviamo il problema di locking dell’I/O error

    Ho recentemente risolto un problema con FreeBSD, SQLite3  e un file-system montato via NFS.

    Veniamo ai dettagli: FreeBSD 9.2-RELEASE (“xray“) monta un file-system condiviso via NFS da un server Linux (“zulu“), già condiviso con altre macchine, e con cui non si presentano problemi particolari.

    Il comportamento particolare di FreeBSD si manifesta quando tento di aprire un database SQLite3 direttamente sul file-system condiviso:

    xray # mount -t nfs -o udp, nfsv3 zulu:/exportnfs /nfs
    xray /nfs % sqlite3 test.sqlite3
    SQLite version 3.8.2 2013-12-06 14:53:30
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> .schema
    Error: disk I/O error

    Dopo varie prove, e constatando che il problema si verifica solo con FreeBSD, mi imbatto nell’interessante articolo sullo strato più basso di SQLite, quello a contatto con il sistema operativo, ovvero il VFS.
    Scopro che, passando l’opzione -vfs unix-dotfiles riesco ad evitare il problema di I/O error.

    Capisco quindi che il problema è tra le opzioni di locking del client NFS di FreeBSD. Soluzione? Leggo il man di mount_nfs e trovo l’opzione nolockd. Faccio un remount ed il problema è risolto!