Пример простого Firewall на базе IPtables для VPS-сервера на базе Ubuntu Linux

by Anton Chernousov aka GITA-DEV


Опубликовано: 03 Авг 2018 (последние правки 1 месяц, 2 недели)


Пример простого Firewall на базе IPtables для VPS-сервера на базе Ubuntu Linux

Для каждого из популярных Linux-дистрибутивов имеется свой собственный Firewall, для Ubuntu Linux это UFW, для Centos и RedHat это Firewalld, у Suse Linux это SuSEfirewall2 и еще несколько местечковых проектов. И естественно, что у каждого из них своя специфика, бережно разбросанные грабли и т.п., наверное именно по этому в 80% случаев на клиентских серверах я вижу не Firewall-пакет дистрибутива, а простой shell-скрипт который отрабатывает при активации интерфейса для которого применяются правила.

Сегодня я хотел бы рассказать именно про этот подход, он простой, эффективный и позволяет строить самые специфичные правила. Начнем с того, что наши скрипты firewall я буду располагать в каталоге /etc/firewall/ и основной скрипт называется firewall.sh, а дополнительные по имени интерфейса (например спец настройки для VPN-интерфейсов). Вы можете придумать какой-то свой способ и придерживаться его.

Правила Firewall применяются на этапе активации (или переподключения) сетевого интерфейса и для реализации этого функционала к настройкам сетевого интерфейса добавляем параметр post-up:

auto eth0 
iface eth0 inet static 
       address 80.211.102.101 
       netmask 255.255.255.0 
       gateway 80.211.102.1 
       dns-nameservers 62.149.128.4 62.149.132.4 
       post-up /etc/firewall/firewall.sh

В случае VPS-сервера этот скрипт будет максимально простым. Нам надо просто запретить все входящие подключения по умолчанию и разрешить только публичные сервисы (ssh/http/mail и т.п.), список портов которые используются на нашем сервере с привязкой к процессу вы можете получить при помощи команды netstat:

# netstat -tulpn 
Active Internet connections (only servers) 
Proto Recv-Q Send-Q Local Address          Foreign Address        State      PID/Program name 
tcp       0     0 0.0.0.0:111            0.0.0.0:*              LISTEN     1268/rpcbind    
tcp       0     0 0.0.0.0:80             0.0.0.0:*              LISTEN     6905/nginx -g daemo 
tcp       0     0 0.0.0.0:22             0.0.0.0:*              LISTEN     1238/sshd       
tcp       0     0 0.0.0.0:58583          0.0.0.0:*              LISTEN     1289/rpc.mountd 
...
udp6      0     0 :::2049                :::*                               -               
udp6      0     0 :::50206               :::*                               1289/rpc.mountd 
udp6      0     0 :::45102               :::*                               -               
udp6      0     0 :::50281               :::*                               1289/rpc.mountd 
udp6      0     0 :::111                 :::*                               1268/rpcbind    
udp6      0     0 :::51014               :::*                               1289/rpc.mountd

Как вы видите список довольно обширный и это типичный пример того, что сервер надо закрывать Firewall, вы так же можете посмотреть как это выглядит при сканировании портов с удаленного компьютера злоумышленника и для этого используйте команду nmap:

# nmap -sV 80.211.102.101 
Starting Nmap 7.01 ( https://nmap.org ) at 2018-08-03 10:15 +07 
Nmap scan report for host101-102-211-80.serverdedicati.aruba.it (80.211.102.101) 
Host is up (0.10s latency). 
Not shown: 994 closed ports 
PORT    STATE SERVICE    VERSION 
22/tcp  open ssh        OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0) 
80/tcp  open http       nginx 1.10.3 (Ubuntu) 
111/tcp open rpcbind    2-4 (RPC #100000) 
...
443/tcp open ssl/http   nginx 1.10.3 (Ubuntu) 
2049/tcp open nfs        2-4 (RPC #100003) 
5432/tcp open postgresql?

Переходим к настройке нашего firewall.sh и первым делом мы заблокируем на этом сервере для доступа из публичной сети все кроме SSH (порт 22) и WEB (80 и 443), а скрипт соответственно приобретает вид:

#!/bin/sh 
 
IPT="/sbin/iptables" 
PUBLIC_INTERFACE="eth0" 
 
# Clean all tables 
# Set default rules 
$IPT -F 
$IPT -X 
$IPT -t nat -F 
$IPT -t nat -X 
$IPT -t mangle -F 
$IPT -t mangle -X 
 
# All Drop by Design 
$IPT -P OUTPUT ACCEPT 
$IPT -P INPUT DROP 
$IPT -P FORWARD DROP 
 
# Allow localnetwork 
$IPT -A INPUT -i lo -j ACCEPT 
$IPT -A FORWARD -o lo -j ACCEPT 
 
# Curent connections 
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
 
# Enable SSH from External Interface 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 22 -j ACCEPT 
 
# Enable WEB from External Interface 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 443 -j ACCEPT 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 80 -j ACCEPT

Все максимально просто (с комментариями) и для последующей переделки под другой сервер, часть параметров вынесена в переменные. Применим эти правила (просто запустите файл) и проверяем открытые порты с удаленного сервера при помощи nmap:

# nmap -sV 80.211.102.101 
 
Starting Nmap 7.01 ( https://nmap.org ) at 2018-08-03 10:33 +07 
Nmap scan report for host101-102-211-80.serverdedicati.aruba.it (80.211.102.101) 
Host is up (0.098s latency). 
Not shown: 997 filtered ports 
PORT   STATE SERVICE VERSION 
22/tcp open ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0) 
80/tcp open http    nginx 1.10.3 (Ubuntu) 
443/tcp open ssl/http nginx 1.10.3 (Ubuntu) 
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 
 
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 
Nmap done: 1 IP address (1 host up) scanned in 23.28 seconds

Как вы видите все стало гораздо лучше, но часть сервисов все же должна быть доступна, но с фиксированных IP-адресов и в моем случае с моей рабочей станции должен быть доступ к Postgresql, а с Failover-сервера должен быть доступ к Postgresql и NFS-серверу. Конструкция не сильно усложняется:

#!/bin/sh 
 
IPT="/sbin/iptables" 
PUBLIC_INTERFACE="eth0" 
 
# Clean all tables 
# Set default rules 
$IPT -F 
$IPT -X 
$IPT -t nat -F 
$IPT -t nat -X 
$IPT -t mangle -F 
$IPT -t mangle -X 
 
# All Drop by Design 
$IPT -P OUTPUT ACCEPT 
$IPT -P INPUT DROP 
$IPT -P FORWARD DROP 
 
# Allow localnetwork 
$IPT -A INPUT -i lo -j ACCEPT 
$IPT -A FORWARD -o lo -j ACCEPT 
 
# Curent connections 
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
 
# Enable SSH from External Interface 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 22 -j ACCEPT 
 
# Enable WEB from External Interface 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 443 -j ACCEPT 
$IPT -A INPUT -i $PUBLIC_INTERFACE -p tcp --dport 80 -j ACCEPT 
 
# Postgreql from fixed IP-addresses 
$IPT -A INPUT -i $PUBLIC_INTERFACE -s 178.49.118.251/32 -p tcp --dport 5432 -j ACCEPT 
 
# Any access from fixed IP-addreses (Failover server) 
$IPT -A INPUT -i $PUBLIC_INTERFACE -s 94.177.204.179/32 -j ACCEPT 
 
exit 0

Честно говоря лучше конечно использовать VPN для реализации безопасного взаимодействия между сервисами, но и такой способ имеет право на существование если обмен данными между сервисами защищен TLS. Для проверки того, что правила к интерфейсу применяются автоматически можно перезагрузить сервер и проверить состояние iptables после перезагрузки:

# iptables -L -n 
Chain INPUT (policy DROP) 
target    prot opt source              destination         
f2b-ssh   tcp -- 0.0.0.0/0           0.0.0.0/0           multiport dports 22 
f2b-sshd  tcp -- 0.0.0.0/0           0.0.0.0/0           multiport dports 22 
ACCEPT    all -- 0.0.0.0/0           0.0.0.0/0           
ACCEPT    all -- 0.0.0.0/0           0.0.0.0/0           state RELATED,ESTABLISHED 
ACCEPT    tcp -- 0.0.0.0/0           0.0.0.0/0           tcp dpt:22 
ACCEPT    tcp -- 0.0.0.0/0           0.0.0.0/0           tcp dpt:443 
ACCEPT    tcp -- 0.0.0.0/0           0.0.0.0/0           tcp dpt:80 
ACCEPT    tcp -- 178.49.118.251      0.0.0.0/0           tcp dpt:5432 
ACCEPT    all -- 94.177.204.179      0.0.0.0/0           
 
Chain FORWARD (policy DROP) 
target    prot opt source              destination         
ACCEPT    all -- 0.0.0.0/0           0.0.0.0/0           
 
Chain OUTPUT (policy ACCEPT) 
target    prot opt source              destination         
 
Chain f2b-ssh (1 references) 
target    prot opt source              destination         
RETURN    all -- 0.0.0.0/0           0.0.0.0/0           
 
Chain f2b-sshd (1 references) 
target    prot opt source              destination         
RETURN    all -- 0.0.0.0/0           0.0.0.0/0

Мы рассмотрели конечно только вершину айсберга, но думаю общая идея понятна.


Обратите внимание на статьи:


Настройка Fail2ban для Asterisk (FreePBX)

Настройка Fail2ban для Asterisk (FreePBX)

Небольшое описание того, как я возился с настройкой Fail2ban в Centos 7. Что интересно, штатные правила конфигурации для FirewallD с виду работают, добавляют заблокированные адреса в соответствующие цепочки, но подключения клиентов все равно не блокируются. Для Asterisk который является просто лакомым кусочком для разного рода жуликов работать без Fail2Ban крайне опасно.


Настройка Firewall в Centos для полноценной работы сервера IP-телефонии

Настройка Firewall в Centos для полноценной работы сервера IP-телефонии

Меня довольно часто спрашивают какие порты необходимо открыть на роутере для работы IP-телефонии. Для работы IP-телефонии на базе протокола SIP, необходимо чтобы был доступен управляющий порт 5060 и поты 10000-20000. Я набросал небольшую инструкцию по настройке FirewallD, возможно она будет вам полезна.


Есть вопросы?
Спрашивайте и я обязательно вам отвечу!

* Поля обязательные для заполнения .

Блог это некоммерческий проект! Если вам понравился мой блог и то что я пишу помогло вам на практике, то можете сказать спасибо материально.