2015년 7월 25일 토요일

Workaround for sync cycle problem between Mnemosyne Android app and Mnemosyne 2.3.3 on local machine

I've been an avid user of Mnemosyne Spaced Repetition Software (SRS) for several years now, and Peter Bienstman's recent development of a free Mnemosyne app for Android has made this software much more useful. I can now do card reviews during my daily subway commute without needing to be in front of a computer.

The Android app still has some rough edges, however. I store my Mnemosyne default.db on Dropbox, and do my card reviews on my work laptop, computers at home, as well as on my Android phone. In my experience, unfortunately, Mnemosyne Android only reliably syncs with the first machine it downloads cards from. So if I do an initial sync from my Dell Latitude notebook to my Android phone, I cannot sync Mnemosyne Android with Mnemosyne installed on my Lenovo laptop at work. If you try to do so, you will get an error message in the Android app stating:

Sync cycle detected. Sync through intermediate partner.

This is frustrating because during my morning and evening commute, I can easily do more than 100 card reviews total. I don't want to lose this record just because the in-app sync from Android to Mnemosyne desktop fails.

I found a variety of posts on the Internet about this issue, some of which advise extraneous steps. Through trial-and-error I found a simple workaround that just requires that you have adb installed on your Linux machine.

Solution: Overwrite default.db on your local machine with default.db from your Android phone

The path for default.db on your Android phone will be something like

/storage/sdcard0/Mnemosyne/default.db

Of course you should verify that this is the case by running adb shell and trying to navigate to /storage/sdcard0/Mnemosyne

adb is provided by the android-tools package on Archlinux. By default, adb has to be run as the root user, but this is not recommended due to security risks. Instead, use a Linux Access Control List (ACL) to allow your regular user to run /usr/bin/adb:

sudo setfacl -m "u:userName:rwx" /usr/bin/adb

This is better than just changing the file owner to some local user using chown or setting SUID on the file. (And much simpler than creating a udev rule just to connect to your phone using adb)
=============================================
Update 2016-10-8
When I wrote this post in July 2015 I initially recommended using ACL's to access your Android device from Linux. Now Archlinux has the package android-udev-rules which contains usb device ID's for popular Android phones. If your device ID isn't contained in the 51-android.rules udev file, simply git clone the android-udev-rules upstream repo on github, add your device ID to the rules file, and submit a pull request to the maintainer, M0Rf30.
=============================================
Connect your Android phone to your Linux machine via USB cable and then run adb devices to make sure the device is being properly detected by the Android Debug Bridge:

[archjun@latitude630 ~]$ adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached 
12B9WQ2B1953661 device

Now run adb shell to find where default.db for Mnemosyne Android is located. Use ls -d */ to only show directories:

[archjun@latitude630 ~]$ adb shell
shell@android:/ $ ls -d */
acct/
cache/
config/
d/
data/
dev/
devlog/
etc/
firmware_q6/
firmware_radio/
mnt/
proc/
root/
sbin/
sdcard/
storage/
sys/
system/
tombstones/
usbdisk/
vendor/
shell@android:/ $ cd storage
shell@android:/storage $ ls -d */
sdcard0/
usbdisk/
shell@android:/storage $ cd sdcard0
shell@android:/storage/sdcard0 $ ls -d */
Alarms/
Android/
Books/
DCIM/
Download/
LOST.DIR/
Mnemosyne/
Movies/
Music/
My Documents/
Notifications/
Pictures/
Podcasts/
Ringtones/
TWRP/
clockworkmod/
data/

tmp/
shell@android:/storage/sdcard0 $ cd Mnemosyne
shell@android:/storage/sdcard0/Mnemosyne $ ls
backups
config.db
config.py
config.pyc
default.db
default.db-journal
default.db_media
history
machine.id
plugins
shell@android:/storage/sdcard0/Mnemosyne $ pwd

/storage/sdcard0/Mnemosyne

Voila! There's default.db! In another terminal window, navigate to the directory where default.db is stored on your local machine. In my case, I store all my Mnemosyne data in ~/Dropbox/mnemosyne, so I would cd into that directory, but YMMV. Now copy the output of pwd above which tells you the current working directory where your Android Mnemosyne file is located and run the following from your local machine's mnemosyne directory:

$ adb pull /storage/sdcard0/Mnemosyne/default.db

Note that you will not be prompted whether or not you want to overwrite the existing .db file on your local machine with the one from your Android phone, so be careful. It is not necessary to copy over other miscellaneous files like config.*, machine.id, etc.

Now if you launch Mnemosyne on your local machine, you will see that the card review data is identical to that of your Mnemosyne Android app. Once the Sync cycle detected error appears on your Mnemosyne Android app, you will probably have to delete all the Mnemosyne info from your phone's SD card and resync from your local machine. To delete the Mnemosyne directory from the sdcard, do the following (assuming your Mnemosyne Android path is /storage/sdcard0/Mnemosyne):

[archjun@latitude630 ~]$ adb shell
shell@android:/ $ rm -rf /storage/sdcard0/Mnemosyne

Now launch your Mnemosyne Android app, and press Sync while Mnemosyne is running on your Linux machine. Make sure that in Settings -> Configure Mnemosyne the Allow other devices to sync with this computer box is checked.

If you are on a distro that uses firewalld (like recent versions of Fedora), make sure that TCP port 8512 is open. A firewalld command that will open this port is the following:

firewall-cmd --add-port=8512/tcp

If you want to permanently add this port, add the option flag --permanent to the command above and then reload firewalld with firewall-cmd --reload

2015년 7월 19일 일요일

Using Linux to Install KitKat 4.4.4 on HTC Sensation with ICS 4.0.3

This post describes the steps I took to unlock the bootloader and get S-OFF (NAND flash memory security off) on my HTC Sensation so that I could install a custom ROM onto a phone that hasn't received Android updates since 2012.

1. Unlock the bootloader

This step is quite easy thanks to the HTCdev website and HTC's enlightened attitude toward modding. After creating an account at http://www.htcdev.com/ and logging in, click the Unlock Bootloader icon pictured below and press the green Get Started button when it appears.



Select your device from the drop-down menu and click the green button, Begin Unlock Bootloader. You will have to click through a waiver stating that unlocking the bootloader may void your warranty and then you have to click on two check boxes to give your consent. Once that's out of the way, you will be given instructions for booting into bootloader mode. On the HTC Sensation, you can achieve this by powering down and pressing Volume Down + Power Button at the same time to restart. For this to work, however, you need to make sure that fastboot is disabled in the Settings -> Battery menu in Android and also that USB Debugging mode is enabled in Settings -> Developer Options.

When the Android bootloader screen appears, using the Up/Down Volume button, navigate to Fastboot and press the power button.

Connect your HTC Sensation to your Linux machine via USB cable. On your phone's screen, select "Charge Only". It may take a few moments for your machine to recognize the phone. To verify that your Linux machine is detecting the Sensation correctly, run lsusb and you should see something like:

[archjun@latitude630 ~]$ lsusb
Bus 002 Device 006: ID 0bb4:0f87 HTC (High Tech Computer Corp.)
...

Once your phone detects it is connected via USB to another machine, the bootloader screen will show Fastboot USB. From HTCdev you can download a zipfile containing the fastboot binary, but since we're on Linux it is better to use your package manager to install the android-tools package (Archlinux) which includes adb (Android Debug Bridge), fastboot, and mkbootimg

On the command line type the following:

sudo fastboot oem get_identifier_token

This will return something like the following (I have replaced the 16-line unlock token with some invalid string):
...
(bootloader)
(bootloader) < Please cut following message >
(bootloader) <<<< Identifier Token Start >>>>
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) ABC123456ABA78987654321A1B2C3X5C
(bootloader) <<<<< Identifier Token End >>>>>
OKAY [  0.064s]
finished. total time: 0.064s

You will need to copy this into your favorite text editor and delete the string (bootloader) as well as the extra whitespace at the beginning of the line. You must also include the lines Identifier Token Start/End. A valid token will look like the following:

<<<< Identifier Token Start >>>>
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C
ABC123456ABA78987654321A1B2C3X5C

ABC123456ABA78987654321A1B2C3X5C
<<<<< Identifier Token End >>>>>

On the HTCdev site, there is a box titled My Identifier Token into which you should copy-paste in the same form as above.

Once you have pasted it into the window and pressed the green Submit button at the bottom of the page, you will be informed that the unlock token will be sent to you in an email attachment named Unlock_code.bin

Download this attachment to your machine, and from the download path run

sudo fastboot flash unlocktoken Unlock_code.bin

If all goes well, the console should output

unlock token check successfully

Your HTC Sensation will then display Unlock bootloader? on its screen:



Move to Yes using the Volume button on the left and then press the Power button.

Congratulations, you have now unlocked the stock bootloader on your HTC Sensation! Note that this erases everything on your SD card and all the data in the internal NAND memory.

In the next step, we will enable writing to the Sensation's internal NAND flash memory (i.e. get S-OFF / security off) so we can write a custom ROM to the phone.


2. Enable Writing to internal NAND Memory (S-OFF)

There are a variety of methods for disabling write protection on the internal memory, but if you have done an Over The Air (OTA) update provided by HTC to upgrade the Sensation to Android 4.0.3 Ice Cream Sandwich, the HBOOT bootloader is upgraded to version 1.27. As a result, you only have one method of disabling S-OFF, which involves something called the "wire trick". At first, I thought that this couldn't be correct, but disabling write protection requires, among other things, connecting one end of a wire to the ground port of the HTC Sensation, and the other end of the wire to the metal case of the SD Card slot:



I unfolded a paper clip and used it for the wire trick above.

I used the Juopunutbear S-OFF method described at the following link:

http://unlimited.io/juopunutbear.htm

Since we already unlocked the bootloader in Step 1 using the unlock token from HTCdev, all the user data is now wiped from the stock ICS Android installation. Once again you must turn off fastboot and enable USB Debugging as detailed in Step 1 above.

Now use a microUSB to USB cable to connect your HTC Sensation to a USB port on a Linux machine. As in Step 1 above, you can verify that your phone is detected by running lsusb and looking for PCI bus ID 0bb4:0f87.

Download the Juopunutbear S-OFF tarball for the HTC Sensation with ICS 4.0.3 from the following link:

http://unlimited.io/downloads/jb/pyramid/ControlBearRelease_pyramid_ICS_LINUX.tgz

Extract files from the tarball with

tar xvfz ControlBearRelease_pyramid_ICS_LINUX.tgz

This tarball contains the binary executables adb, fastboot, and ControlBear in addition to a variety of .img files. Although adb and fastboot should already be installed from the android-tools package, I suspect that the ControlBear program uses the versions of adb and fastboot extracted from the tarball (although I can't be sure, since I haven't been able to find a copy of the source for ControlBear).

The instructions from http://unlimited.io/juopunutbear.htm tell users to give rwx r-x r-x permissions to Controlbear with chmod 755 ControlBear and to run the ControlBear binary as root. I wish I could see exactly what steps this program takes to get S-OFF...

ControlBear will tell you when it is time to do the wire trick. While you are waiting to get the go-ahead, initially insert one end of a paper clip into the ground port on the right, and when the terminal tells you to do the wire trick, tap the other end of the paper clip to the metal casing of the SD Card slot for a little more than one second, wait one second, and then repeat. You may have to run ControlBear several times before you execute the wire trick perfectly. If you have problems, refer to the ControlBear troubleshooting FAQ for more info:

http://unlimited.io/jbtroubleshooting.htm

If ControlBear succeeds, you will get the following message:

...
SUCCESS - Buddies and Beer
Checking alcohol level......
Seems to be just right.....
Let's take one more......
Aaaah, nice sunny day!!
Rebooting.......
Waiting device....
Found device... Please wait...
Rebooting bootloader.......
Waiting device....
Fastboot detected
JuopunutBear S-OFF success

ControlBear will then prompt you whether or not you want to install a custom HBOOT bootloader. If you do install the custom HBOOT, when you restart your phone, you will see that S-OFF is enabled but find that the bootloader is LOCKED again. I suspect that if you don't install the custom Juopunutbear bootloader, the HBOOT 1.27 which we unlocked in Step 1 using the token from HTCdev will remain unlocked (but I haven't tested this yet on my Sensation).

Although some tutorials on the Internet claim that as long as you have S-OFF enabled, it doesn't matter if the bootloader is locked or not, this was not the case for me. I had to repeat the Step 1 process once more to unlock the Juopunutbear custom bootloader before I could proceed to the next step.


3. Install a Custom Recovery Bootloader - TWRP

Through trial-and-error, I found that recent builds of Team Win Recovery Project (TWRP) for the HTC Sensation are capable of installing newer Android versions like KitKat 4.4.4 and Lollipop 5.0+. Although ClockWork Mod (CWM) recovery is very popular on Android forums, the latest version available for the HTC Sensation at this link is below version 6.

Unfortunately, CWM Recovery below version 6.0.4.5 is not capable of installing Android KitKat.

This isn't a problem as TWRP has recent builds for the HTC Sensation at the following link:

https://twrp.me/devices/htcsensation.html

Instead of installing TWRP from the Google Play Store, simply download the image file from the following link (which is also listed on the TWRP HTC Sensation page):

https://dl.twrp.me/pyramid/

Select the most recent version, which as of July 19, 2015 is twrp-2.8.6.0-pyramid.img

Once you have downloaded the TWRP image, you will use adb to install TWRP as the new recovery bootloader. As explained in Step 1 above, make sure fastboot is disabled and that USB Debugging is enabled. Connect the HTC Sensation to your Linux machine's USB port and enter the following in a terminal:

sudo adb reboot bootloader

In your terminal, make sure you are in the same PATH to which you downloaded twrp-2.8.6.0-pyramid.img

When you get to the bootloader screen, you can now flash TWRP to your phone:

sudo fastboot flash recovery twrp-2.8.6.0-pyramid.img


4. Copy an Android KitKat Image to the phone's sdcard

Because the HTC Sensation only has 768 MB RAM and 1024 MB internal NAND memory, I deliberately chose the minimal Android distribution SlimKat. I've heard that the dual-core HTC Sensation feels sluggish on Android Lollipop 5.0, so I downloaded SlimKat's Slim-pyramid-4.4.4.build.9.0-OFFICIAL-8305.zip KitKat image. The nice thing about TWRP is that you can install Android from .zip instead of .img files, so it is unnecessary to extract files from the zip archive.

To send the KitKat image file to the HTC Sensation, use the adb push command:

sudo adb push Slim-pyramid-4.4.4.build.9.0-OFFICIAL-8305.zip /storage/sdcard0


5. Install Custom KitKat Image using TWRP

Now reboot into recovery mode, which should bring up TWRP:

sudo adb reboot recovery

Alternately, you could manually power off the Sensation, and then press the Volume Down and Power buttons simultaneously at boot to enter recovery mode.

Before you install the custom KitKat ROM, you must first flush the Dalvik cache. From the TWRP menu, tap Wipe and make sure Dalvik Cache is checked. As for why it is a good idea to wipe this cache, refer to this post from Stack Exchange.

Next, from the TWRP main menu, select Install and when it prompts you to Select Zip to Install, navigate to the path on the sdcard (/storage/sdcard0) where you saved the KitKat .zip file.

Once this process finishes, you will have an HTC Sensation running Android 4.4.4!

2015년 7월 9일 목요일

Unable to reload rules in firewalld 0.3.14.2-1 Archlinux (workaround: restart firewalld.service)

firewalld is an upstream dynamic firewall project from Fedora. Personally, I find working with firewalld to be much more pleasant than trying to decipher and write arcane iptables static firewall rules.

Although Archlinux is generally a cutting-edge Linux distro that gives users access to the newest packages from upstream and the newest kernels, in my humble opinion it lags behind Fedora/RHEL/CentOS in the security department. SELinux and firewalld are setup by default in Fedora et al, but in Archlinux only firewalld is available from the default repositories. As of June 2015, SELinux can be installed on Arch, but SELinux policies have not been customized for Archlinux (i.e. the default policies assume Fedora/RHEL paths and filenames).

A test machine running Arch and firewalld also happened to be an NFS server, but NFS clients could no longer connect to the server because of the firewall. Since I only use NFS within my LAN, I assigned the Ethernet port enp1s0 to the firewalld internal zone and then added NFS-related services to internal as follows:

$ sudo firewall-cmd --zone=internal --change-interface=enp1s0
[sudo] password for archjun: 
success
$ sudo firewall-cmd --permanent --zone=internal --add-service=nfs
success
$ sudo firewall-cmd --permanent --zone=internal --add-service=rpc-bind
success
$ sudo firewall-cmd --permanent --zone=internal --add-service=mountd

Now to apply this to firewalld, we need to reload the firewall rules:

$ sudo firewall-cmd --reload
Error: 'NoneType' object has no attribute 'query_rule'

I verified that the services I added above (nfs, rpc-bind, and mountd) were not yet reflected in firewalld:

$ firewall-cmd --zone=internal --list-all
internal (active)
  interfaces: enp1s0
  sources: 
  services: dhcpv6-client mdns samba-client ssh
  ports: 
  masquerade: no
  forward-ports: 
  icmp-blocks: 
  rich rules:

I looked for any firewalld-related errors in the systemd journal journalctl, but found nothing of interest.

Googling for the error above did not turn up any relevant results. I also tried to use the firewalld GUI, firewall-config, and clicked the checkbox for each service to whitelist in Zone internal :



Changing Runtime rules only works for the current session, but you can also define Permanent rules, too. I assumed that changing Runtime rules in the GUI would be immediately applied, but this was not the case; I am not sure if this is a problem with firewall-config in Archlinux or a lack of understanding on my part. When I clicked Options -> Reload Firewalld, I got the exact same error that firewalld-cmd gave me:

'NoneType' object has no attribute 'query_rule'



As a last resort, I invoked

$ sudo systemctl restart firewalld

After restarting systemd's firewalld.service, you can see that the permanent rule changes I made to the internal zone with firewall-cmd finally appear:

$ firewall-cmd --zone=internal --list-all
internal (active)
  interfaces: enp1s0
  sources: 
  services: dhcpv6-client mdns mountd nfs rpc-bind rsyncd samba-client ssh
  ports: 
  masquerade: no
  forward-ports: 
  icmp-blocks: 
  rich rules:

*Note: although firewalld calls "rpcbind" rpc-bind, the name of the systemd service is rpcbind.service, not rpc-bind.service.


Update 2015-07-10

On another Archlinux machine using the Openbox Desktop Environment, reloading firewalld rules with firewall-cmd --reload works just fine. The problem I have described in this post occurred on an Archlinux machine using the LXDE desktop environment. Perhaps the problems I experienced are somehow related to LXDE?

References:

https://fedoraproject.org/wiki/User:Renich/HowTo/NFSv4 (with firewalld)

https://fedoraproject.org/wiki/FirewallD#Using_firewall-cmd

2015년 7월 4일 토요일

Setting up fail2ban on CentOS 7 with firewalld on a Digital Ocean droplet

When running a server in the cloud, it is a good idea to at least secure SSH so that brute forcing attempts will automatically be blocked after a set number of incorrect tries. Having set up fail2ban with firewalld in Archlinux on a laptop, I figured the process would be pretty much the same for CentOS 7 in a Digital Ocean droplet.

As soon as you login into your new Droplet, I recommend that you follow the steps in this DO article about creating a regular user account, enabling sudo, disabling root logins over SSH, etc. You should also read the follow-up article about how to set up firewalld in CentOS 7 (TL;DR sudo systemctl enable firewalld, sudo systemctl start firewalld)

Now you need to install fail2ban. Although it is not in the default CentOS yum repositories, it is available through EPEL which is included in the CentOS Extras repository (which is enabled by default).

sudo yum install epel-release

Starting from RHEL/CentOS 7, iptables and rsyslog have been replaced with firewalld and journalctl (part of systemd), so you must be sure to yum install the following packages:

fail2ban-systemd (to ensure journalctl compatibility)
fail2ban-firewalld
ipset (to ban IP's with firewalld)
fail2ban-server

Now cd into /etc/fail2ban where you will see the systemwide fail2ban config file jail.conf which you can use as a reference but should not edit directly. Instead, in the subdir /etc/fail2ban/jail.d/ you should make your own config file ending with the .conf extension (I named mine local.conf). You will also notice that in this sub-directory there will be two other .conf files named 00-firewalld.conf and 00-systemd.conf which contain the following:

[centjun@juncent7 jail.d]$ cat 00-firewalld.conf 
# This file is part of the fail2ban-firewalld package to configure the use of
# the firewalld actions as the default actions.  You can remove this package
# (along with the empty fail2ban meta-package) if you do not use firewalld
[DEFAULT]
banaction = firewallcmd-ipset

[centjun@juncent7 jail.d]$ cat 00-systemd.conf 
# This file is part of the fail2ban-systemd package to configure the use of
# the systemd journal as the default backend.  You can remove this package
# (along with the empty fail2ban meta-package) if you do not want to use the
# journal backend
[DEFAULT]
backend=systemd

In Archlinux, these config files are not included in the jail.d subdir, so I had to add banaction=... and backend=... in local.conf (in the case of Archlinux, not CentOS7).

The /etc/fail2ban/jail.d/local.conf which I used in Archlinux is as follows:

[DEFAULT]
bantime = 18000
banaction = firewallcmd-ipset
backend = systemd
sender = fail2ban@example.com
destemail = root
ignoreip = 127.0.0.1 192.168.0.0/16
use_dns = no
maxretry = 21

action = %(action_mwl)s

[sshd]
enabled = true

However when I used the settings above in CentOS 7 and then tried to start the fail2ban systemd service with sudo systemctl start fail2ban I got the following errors in journalctl:

Jul 04 14:36:19 juncent7 fail2ban-client[1674]: ERROR  Found no accessible config files for 'action.d/sendmail-whois-lines' under /e...ail2ban
Jul 04 14:36:19 juncent7 fail2ban-client[1674]: ERROR  Error in action definition sendmail-whois-lines[name=sshd, dest="centjun", lo...INPUT"]
Jul 04 14:36:19 juncent7 fail2ban-client[1674]: ERROR  Errors in jail 'sshd'. Skipping...

Since fail2ban uses sendmail as its default mta, I checked to see if sendmail was installed:

[centjun@juncent7 jail.d]$ rpm -q sendmail
package sendmail is not installed

Instead, I found that postfix was installed, so I then added mta = postfix to local.conf, but still got similar errors:

Jul 04 14:45:13 juncent7 fail2ban-client[1715]: ERROR  Found no accessible config files for 'action.d/postfix-whois-lines' under /etc/fail2ban
Jul 04 14:45:13 juncent7 fail2ban-client[1715]: ERROR  Error in action definition postfix-whois-lines[name=sshd, dest="centjun", log...INPUT"]
Jul 04 14:45:13 juncent7 fail2ban-client[1715]: ERROR  Errors in jail 'sshd'. Skipping...

I checked /etc/fail2ban/action.d/ for the files postfix-whois-lines and sendmail-whois-lines but both of the them were nowhere to be found.

Finally I edited the default action in local.conf to just ban the offending IP instead of sending a mail to root:

action = $(action_)s

Now when starting fail2ban.service with systemctl start fail2ban, everything works fine:

[centjun@juncent7 jail.d]$ systemctl status fail2ban
fail2ban.service - Fail2Ban Service
   Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; enabled)
   Active: active (running) since Sat 2015-07-04 15:08:04 SGT; 44min ago
     Docs: man:fail2ban(1)
  Process: 1803 ExecStart=/usr/bin/fail2ban-client -x start (code=exited, status=0/SUCCESS)
 Main PID: 1806 (fail2ban-server)
   CGroup: /system.slice/fail2ban.service
           └─1806 /usr/bin/python -Es /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -x -b

[centjun@juncent7 jail.d]$ sudo fail2ban-client status
[sudo] password for centjun:
Status
|- Number of jail:      1
`- Jail list:   sshd

Just in case you think it is too much hassle to do minimal server hardening, take a look at just a few of the dozens of unauthorized login attempts recorded by PAM in journalctl:

Jul 04 15:21:42 juncent7 sshd[1828]: reverse mapping checking getaddrinfo for 107.30.65.218.broad.xy.jx.dynamic.163data.com.cn [218...ATTEMPT!
Jul 04 15:21:43 juncent7 sshd[1828]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.65...ser=root
Jul 04 15:21:43 juncent7 sshd[1828]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:21:45 juncent7 sshd[1828]: Failed password for root from 218.65.30.107 port 57804 ssh2
Jul 04 15:21:45 juncent7 sshd[1828]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:21:47 juncent7 sshd[1828]: Failed password for root from 218.65.30.107 port 57804 ssh2
Jul 04 15:21:49 juncent7 sshd[1828]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:21:51 juncent7 sshd[1828]: Failed password for root from 218.65.30.107 port 57804 ssh2
Jul 04 15:21:54 juncent7 sshd[1828]: Received disconnect from 218.65.30.107: 11:  [preauth]
Jul 04 15:21:54 juncent7 sshd[1828]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.65.30.107  user=root
Jul 04 15:21:55 juncent7 sshd[1830]: reverse mapping checking getaddrinfo for 107.30.65.218.broad.xy.jx.dynamic.163data.com.cn [218...ATTEMPT!
Jul 04 15:21:55 juncent7 sshd[1830]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.65...ser=root
Jul 04 15:21:55 juncent7 sshd[1830]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:21:58 juncent7 sshd[1830]: Failed password for root from 218.65.30.107 port 53038 ssh2
Jul 04 15:22:03 juncent7 sshd[1830]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:22:04 juncent7 sshd[1830]: Failed password for root from 218.65.30.107 port 53038 ssh2
Jul 04 15:22:05 juncent7 sshd[1830]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jul 04 15:22:06 juncent7 sshd[1830]: Failed password for root from 218.65.30.107 port 53038 ssh2
Jul 04 15:22:07 juncent7 sshd[1830]: Received disconnect from 218.65.30.107: 11:  [preauth]
...

When I switched to root user PAM informed me of a large number of failed login attempts on the root account:

[centjun@juncent7 jail.d]$ su -
Password:
Last login: Fri Jul  3 23:08:03 SGT 2015 from xxx.xxx.xxx.xxx (redacted) on pts/0
Last failed login: Sat Jul  4 15:22:42 SGT 2015 from 218.65.30.107 on ssh:notty
There were 65 failed login attempts since the last successful login.

This large number of unsuccessful logins occurred within just 1 hour of launching my new droplet!

When I ran a reverse DNS on one of the IP's associated with a failed login, it appeared to be an address from China.


Comments on certain settings in /etc/fail2ban/jail.d/local.conf

ignoreip = 

It is a good idea to put your remote IP (the IP of the computer you are connecting from) into ignoreip above (multiple IP's can be entered in the whitelist, separated with spaces) to avoid getting locked out of your cloud server by an attacker sending packets with a spoofed source header (of course the attacker would have to know your remote IP address).

use_dns = no

It is safer not to use dns to ban hostnames because an attacker can change the PTR of an IP that they control to point to another hostname that could make fail2ban to mistakenly ban valid domains (http://www.fail2ban.org/wiki/index.php/Hostnames_or_IP_Addresses).


Thoughts about Digital Ocean Droplets

I was pleasantly surprised with my first experience using Digital Ocean (DO) cloud instances. The only other cloud server I have used is AWS EC2 (free usage tier) and I think DO compares favorably. Although DO is missing the "enterprisey" features of AWS, I think DO is much easier to use and better-suited for quickly spinning up a server instance in the cloud. Whereas AWS micro instances only give you 8GB of storage and 1 CPU, DO's smallest instance gives you 1 CPU with 30 GB of SSD!

For me, DO's killer feature is the ability to take a snapshot of an instance (once you have shut it down), delete the Droplet, and then later create a new Droplet from the snapshot you created earlier. The reason this is so awesome is that DO snapshots are free (unlike those on AWS EC2, which take up gigabytes of Elastic Storage) and allow you to use cloud instances on an hourly basis if you are so inclined. Here are some good forum posts about using DO on an hourly basis:

https://www.digitalocean.com/community/questions/pricing-monthly-or-hourly

https://www.digitalocean.com/community/questions/restore-snapshot-after-destroying-a-droplet

On AWS EC2, however, snapshots are destroyed along with an image, so you couldn't easily replicate this DO feature over there.

References:

https://fedoraproject.org/wiki/Fail2ban_with_FirewallD
Fedora wiki about setting up fail2ban with firewalld; also explains the meaning of variables in fail2ban config files

https://wiki.gentoo.org/wiki/Fail2ban#Actions
Gentoo wiki about fail2ban