Открытие портов после успешного ssh соединения

Зачем?

Port knocking уязвим к атакам с перехватом сетевых данных, а также требует дополнительного ПО (скрипт или приложение для android/ios/…), что не всегда удобно. Но при этом нужно как-то закрыть дополнительным образом некоторые порты.

Правим pam

Нужно добавить строку

session     optional    pam_exec.so /path/to/open_port.sh

самым последним элементом в списке для удаленной аутентификации, например, в случае с gentoo:

host ~ # cat /etc/pam.d/system-remote-login 
auth        include     system-login
account     include     system-login
password    include     system-login
session     include     system-login
session     optional    pam_exec.so /path/to/open_port.sh

Скрипт для открытия порта

#!/bin/bash
[ "$PAM_TYPE" = "open_session" ] || exit 0

function open_port_ip() {
    IP=$1
    PORT=$2
    iptables -A INPUT -m state --state NEW -s ${IP} -p tcp --dport ${PORT} -j ACCEPT
}

function close_port_ip() {
    IP=$1
    PORT=$2
    iptables -D INPUT -m state --state NEW -s ${IP} -p tcp --dport ${PORT} -j ACCEPT
}

function timeout_open_port_ip() {
    IP=$1
    PORT=$2
    TIMEOUT=$3
    open_port_ip ${IP} ${PORT}
    sleep ${TIMEOUT} && close_port_ip ${IP} ${PORT} &
}

function main() {
    for IP in $(who | grep -o -P '(?<=\().*(?=\))' | sort | uniq); do
        timeout_open_port_ip ${IP} 80 30s
    done
}

sleep 1s && main &

Зачем нужен sleep? Дело в том, что удаленные IP адреса в данном случае получаются с помощью команды who, а для того, чтобы там был нужный IP адрес, необходимо, чтобы pam полностью отработал.