This is part 10 of a series of posts on server security from Inversoft's 2016 Guide to User Data Security.

Since most servers aren't actively logged into on a frequent basis, you should be notified when anyone logs into the server. There are many ways to handle this, but we will cover how to setup notifications using a tool called Monit. Monit allows you to watch log files for messages that contain certain text and generate alerts. To install Monit, execute this command in the root terminal window:

$ apt-get install monit

After Monit is installed, you can create a configuration file to monitor SSH login. Copy and paste the configuration below into the file /etc/monit/conf.d/ssh-logins :

check file ssh_logins with path /var/log/auth.log # Whitelist IPs here if you want # ignore match "/etc/monit/whitelist_ips.regex" if match "Accepted keyboard-interactive/pam" then alert

This file states that Monit should watch the file /var/log/auth.log and if it sees new lines that contain the expression "Accepted keyboard-interactive/pam" an alert should be generated. Since you configured two-factor authentication above, the SSH system will insert a log into this file that matches this pattern. If you did not enable two-factor authentication above (and are only using key based authentication) your configuration should instead match on the string "Accepted publickey" .

You can also whitelist certain IP addresses by uncommenting the ignore match line and creating the file /etc/monit/whitelist_ips.regex . This file would contain regular expressions for each whitelisted IP on a separate line.

The last step to configuring Monit is to edit the file /etc/monit/monitrc . Add the lines below to configure Monit to send email alerts to you. This configuration will vary depending on your SMTP mail server, the authentication required for your SMTP server and your email address. Our examples use Sendgrid for sending emails and my email address.

set mailserver smtp.sendgrid.net port 587 username "<sendgrid-username>" password "<sendgrid-password>" using tlsv12 set alert brian@inversoft.com not on { instance, action }

The second line tells Monit to email me whenever alerts happen, but to ignore alerts I created manually. This will reduce spamming your inbox if you choose to use Monit for other tasks such as process watching and restarting.

You might want to receive Monit notifications quickly. By default, Monit runs checks every 2 minutes. Rather than wait two minutes, you can change this setting to something smaller like 5 seconds. This configuration parameter is near the top of the /etc/monit/monitrc file and looks like this:

set daemon 5

Finally, restart the Monit daemon so that it picks up the configuration change:

$ service monit restart

As an added option, you can have Monit send push notifications to your mobile devices and/or send notifications to a Slack channel. One option for handling push notifications is using the Pushover service. To implement this you need to change the last line in /etc/monit/conf.d/ssh-logins to this:

if match "Accepted keyboard-interactive/pam" then exec "/etc/monit/monit-slack-pushover.rb"

Then copy this Ruby script into the file /etc/monit/monit-slack-pushover.rb :

#!/usr/bin/ruby require 'net/https' require 'json' slack_webhook_url="" slack_enabled=true pushover_application="" pushover_user="" pushover_enabled=true def log(message) open('/var/log/monit.log', 'a') { |f| f.puts message } end if slack_enabled begin uri = URI.parse(slack_webhook_url) Net::HTTP.start(uri.host, uri.port, {use_ssl: true}) { |http| request = Net::HTTP::Post.new(uri.request_uri, {'Content-Type' => 'application/json'}) request.body = { :text => "[#{ENV['MONIT_HOST']}] #{ENV['MONIT_SERVICE']} - #{ENV['MONIT_DESCRIPTION']}" }.to_json response = http.request(request) log("Response from Slack [#{response.code}] [#{response.body}]") } rescue Exception => e log("Exception while calling Slack [#{e.message}]") end end if pushover_enabled begin uri = URI.parse("https://api.pushover.net/1/messages.json") Net::HTTP.start(uri.host, uri.port, {use_ssl: true}) { |http| request = Net::HTTP::Post.new(uri.request_uri, {'Content-Type' => 'multipart/form-data'}) request.set_form_data(token: pushover_application, user: pushover_user, message: "[#{ENV['MONIT_HOST']}] #{ENV['MONIT_SERVICE']} - #{ENV['MONIT_DESCRIPTION']}") response = http.request(request) log("Response from Pushover [#{response.code}] [#{response.body}]") } rescue Exception => e log("Exception while calling Pushover [#{e.message}]") end end

You must configure the Pushover and Slack variables defined at the top of the file for the integrations to work properly. For the Pushover integration, create a Pushover account and a Pushover application. The Pushover application creation looks like this:

Give your Pushover application a name, description and URL. Select "Script" from the Type select box.

Once you create the Pushover application it will have an id associated with it. Take the Pushover application and user ids and put them into the variables pushover_application and pushover_user in the script above. Enable Pushover in the script by setting the variable pushover_enabled to true.

For Slack integration, configure an Incoming Webhook using these steps:

Open your Slack interface and click on the name in the top left corner. Select "Apps & Integrations". Click "Build your own" in top right corner. Click "Make a Customer Integration" under "Just for my team". Here you'll select the channel you want to post to. You'll have some other options to set if you want. All you need from here is the integration URL. Copy and paste that URL into the variable slack_webhook_url in the script above.

To ensure the Ruby script above will run properly, make sure you have Ruby installed and the script is executable by executing these commands:

$ apt-get install ruby $ chmod +x /etc/monit/monit-slack-pushover.rb

Finally, restart Monit again using this command: