Monitoring SSH connections to a Linux Server

If you have an internet-facing server, and that despite applying all the patches, securing everything, you want to keep an eye on your server activity and you want to be notified when someone is logging-in with SSH, here is a small and efficient trick !

The idea is to call a script every time an SSH session is opened. Within your script, you can decide what kind of notification you want: mail, telegram, push notification (https://docs.ntfy.sh/ is a good option) …

Step 1 – edit /etc/pam.d/sshd

At the end of the PAM configuration file, add the following line:

# Notify at connection
session optional pam_exec.so /data/admin/scripts/notify_on_ssh.sh

At every SSH connection, PAM will call your script, and pass some environment variables. be sure that your script can be called by the user running SSH. According to the documentation, PAM_EXEC will “Per default pam_exec.so will execute the external command with the real user ID of the
calling process. Specifying this option means the command is run with the effective
user ID.”

Step 2 – create your notification script

As per the documentation, the script will be called for all events: successful and non-successful ! If you want to filter on success events only, use the environment variable PAM_TYPE.

I do personally use simple mail notifications for this purpose:

#!/bin/bash

if [ "${PAM_TYPE}" != "open_session" ]; then
  exit
fi

STMP="mail.xxx.com"
FROM="srv01@xxx.com"
TO="xxx@gmail.com"

SUBJECT="SSH Alert"
CONTENT="A User has logged in.\n\nUser: ${PAM_USER}\nOrigin: ${PAM_RHOST}"

echo -e "To: ${TO}\nFrom: ${FROM}\nSubject: ${SUBJECT}\n${CONTENT}" | ssmtp ${TO}

Change VLAN Priority using Linux bridge

Following my objective of increasing home FTTH bandwith by removing ISP set-top-box, I needed to change the VLAN priority of the DHCP packets (priority 6).

In previous articles, I patched the DHCP client of OpenWRT which uses raw sockets to use priority 6.

Now my objective is to use a standard router such as Mikrotik, which do not support the DHCP packet CoS by default.

I decided to use my Macchiatobin running a custom kernel and OpenWRT and configure it as a bridge which modifies the VLAN priority of specific packets.

This was actually easier than expected!

When creating a bridge, it is important to understand that we are operating at layer 2. A typical bridge is not inspecting packets at higher layers (3 and up), and as such not interacting at IP level.

There is however an option to change this behavior, and to force the processing of packets by the kernel at IP layer!

Just try the following command to enable the processing of bridge packets through iptables:

echo "1" > /proc/sys/net/bridge/bridge-nf-call-iptables

This change can be made persistent by altering sysctl configuration file in /etc/sysctl.d/.

net.bridge.bridge-nf-call-iptables=1

Now that the packets are being processed by iptables, the steps are the following:

  1. Define VLAN interfaces
  2. Create the bridge and attach interfaces
  3. Create iptables rule to change the VLAN priority of selected packets

Defining VLAN interfaces

Why defining every VLAN, instead of just bridging interface as a trunk ? If you do that, the kernel will not have any knowledge about packets, and especially that 802.1Q is in use. And as VLAN priority is a feature that comes with 802.1Q – no VLAN = no priority !

Declare VLAN on the interfaces you wish to bridge, and specify the egress map, to indicate that packets with CoS set to 6 will be leaving the interface with a VLAN priority set to 6:

ip link add link eth0 name eth0.832 type vlan id 832
ip link set eth0.832 type vlan egress 6:6

ip link add link eth3 name eth3.832 type vlan id 832
ip link set eth3.832 type vlan egress 6:6

Create the bridge

Now, it is time to create the bridge and add the interfaces to it. Note that we don’t need to define an IP configuration for this interface (br0) as we just want the device to be a “passive” bridge.

brctl addbr br0
brctl addif br0 eth0.832
brctl addif br0 eth3.832

Create iptables rule to change the CoS of selected packets

The only packets we want to alter is DHCP configuration. Those packets typically have a predefined source and destination port, making it easy.

iptables -A FORWARD -p udp --sport 68 --dport 67 -j CLASSIFY --set-class 0:6

Here we are! At this stage, the device is operating as a bridge, bridging vlan 832 and changing the priorty of DHCP packets to 6.

Persisting this configuration with OpenWRT

If you use OpenWRT and want to persist this configuration, here are the changes.

# /etc/config/network

config device
	option type '8021q'
	option ifname 'eth3'
	option vid '832'
	option name 'eth3.832'
	option ipv6 '0'
	list egress_qos_mapping '6:6'
	list egress_qos_mapping '0:0'
	list egress_qos_mapping '1:0'
	list egress_qos_mapping '2:0'
	list egress_qos_mapping '3:0'
	list egress_qos_mapping '4:0'
	list egress_qos_mapping '5:0'

config device
	option type '8021q'
	option ifname 'eth0'
	option vid '832'
	option name 'eth0.832'
	option ipv6 '0'
        list egress_qos_mapping '6:6'
        list egress_qos_mapping '0:0'
        list egress_qos_mapping '1:0'
        list egress_qos_mapping '2:0'
        list egress_qos_mapping '3:0'
        list egress_qos_mapping '4:0'
        list egress_qos_mapping '5:0'

config interface 'br0'
	option type 'bridge'
	option ifname 'eth3.832 eth0.832'
# /etc/sysctl.d/11-br-netfilter.conf

net.bridge.bridge-nf-call-arptables=0
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=1
# /etc/firewall.user

iptables -A FORWARD -p udp --sport 68 --dport 67 -j CLASSIFY --set-class 0:6