оригинал статьи http://habrahabr.ru/post/146116/
Файервол представляет из себя bash-скрипт, который интегрирует с помощью соответствующих пакетов следующие функции:
- Файервол внешний и внутренний (пакет iptables).
- Учёт трафика внешнего и внутреннего (пакет iptables).
- Прокси-сервер для локальных сетей (пакет Squid).
- Контент-фильтр для локальных сетей (пакет DansGuardian).
- DNS-сервер для локальных сетей (пакет BIND).
Скрипт является результатом многолетней работы и претендует на
универсальность — он позволяет использовать Linux-машину в качестве
Интернет-шлюза как для небольшого офиса, так и для большого предприятия
(на данный момент он используется на пяти предприятиях и в одном
удалённом офисе — везде стоит
CentOS).
Скрипт требует для своей работы наличие как минимум двух сетевых интерфейсов — один из которых является
внешним, а остальные считаются
внутренними. Внешний интерфейс задаётся переменной
EXTIF и определяется автоматически, если эта переменная не задана.
Ещё одно требование — все интерфейсы должны иметь статические адреса,
т.е. интерфейсы могут получать их динамически, но адреса должны быть
всегда одними и теми же. Это требование вытекает из того, что в правилах
iptables используются IP-адреса интерфейсов. Правила генерируются и применяются на основе файла конфигурации
fwtraf.conf по команде "
fwtraf fwnormal" и сохраняются по команде "
fwtraf fwsave".
Т.е. если IP-адреса интерфейсов изменились, нужно будет опять применить
правила (и сохранить их, если нужно чтобы они действовали после
перезагрузки).
Режимы работы source NAT и web-прокси можно комбинировать:
- source NAT: выкл. (SNAT="")
- source NAT: вкл. (SNAT=«YES»).
- web-прокси: выкл. (WEBPROXY="")
- web-прокси: Squid (WEBPROXY=«SQUID»).
- web-прокси: DansGuardian->Squid (WEBPROXY=«DGSQUID»).
Скрипт поддерживает несколько
локальных сетей (переменная
LANS) — они перечисляются через пробел:
LANS=«192.168.0.0/24 10.0.0.0/8»
Также поддерживаются
удалённые локальные сети — например, локальные сети офисов, подключенные по технологиям
VPN (переменная
REMOTE_LANS):
REMOTE_LANS=«192.168.1.0/24 192.168.3.0/24 192.168.5.0/24»
Скрипт имеет простой конфигурационный файл:
В нём указаны статические IP-адреса и имена компьютеров пользователей, которым:
- разрешаются (команда a — сокращение от "allow")
- запрещаются (команда d — сокращение от "deny")
порты (колонка
PORTS):
- один или несколько TCP-портов через запятую: web,ftp.
- все TCP-порты кроме, например, smtp: !smtp.
- все TCP и UDP-порты: all.
Если используется контент-фильтр (WEBPROXY=«DGSQUID») и пользователю разрешаются web-порты, то к нему применяется группа web-доступа (колонка
WA — сокращение от "
Web
Access").
Очень просто делается так называемый проброс портов внешнего
интерфейса на внутренние IP-адреса локальных сетей (destination NAT).
Это удобно, когда на шлюзе включен режим SNAT и локальные сети из
Интернет недоступны. Например, разрешим админу с его компьютера доступ к
Интернет (web и ftp-трафик) и ещё разрешим ему подключаться из Интернет
по RDP на внешний IP-адрес шлюза, а шлюз будет перенаправлять
rdp-трафик на его компьютер:
a 192.168.1.240 pc30 web,ftp,rdp-rdp # Админ
Ещё замечу, что пробрасываемые порты не обязаны совпадать — можно,
например, слушать порт 2525 на внешнем IP, а пробрасывать его на 25-й порт почтового сервера, находящегося внутри локальной сети:
a 192.168.1.2 mail 2525-25 # Почтовый сервер
Скрипт также ежедневно создает html-отчеты о трафике и ежечасно их обновляет:
Установка
1. Скачиваем скрипт файервола и помещаем его в
/bin/:
wget
dl.dropbox.com/u/924293/fwtraf/fwtraf
mv fwtraf /bin/
chmod 755 /bin/fwtraf
2. Скачиваем файл конфигурации файервола и помещаем его в
/etc/fwtraf/:
wget
dl.dropbox.com/u/924293/fwtraf/fwtraf.conf
mkdir /etc/fwtraf
mv fwtraf.conf /etc/fwtraf/
3. Скачиваем файл для планировщика задач
Cron и помещаем его в
/etc/cron.d/:
wget
dl.dropbox.com/u/924293/fwtraf/fwtraf.cron
mv fwtraf.cron /etc/cron.d/
4. Читаем файл
/etc/fwtraf/fwtraf.conf и редактируем его в соответствии со своими
потребностями.
5. После редактирования
fwtraf.conf применяем правила файервола:
fwtraf fwnormal - нормальный (рабочий) режим.
fwtraf fwsave - все правила сохраняются и действуют после перезагрузки.
Существует режим с минимальным набором правил:
fwtraf fwsimple - простой режим, персональные правила не действуют, всё разрешено.
Остальные команды можно узнать так:
fwtraf - справка по командам.
Для включения поддержки работы с
BIND (внимание: будут презаписываться DNS-зоны!) нужно раскомментировать строку c "DNSROOTDIR=..." в
/bin/fwtraf.
СКРИПТЫ
/bin/traf
#!/bin/bash
#
# -------------- ----------- ---------------
# | PREROUTING | | FORWARD | | POSTROUTING |
# -->|------------|-->|---------|-->|-------------|-->
# | mangle | | mangle | | mangle |
# | nat | | filter | | nat |
# -------------- ----------- ---------------
# || /\
# || ||
# \/ ||
# -------------- --------- ---------------
# | INPUT | | | | OUTPUT |
# |------------|-->| LOCAL |-->|-------------|
# | mangle | | PROCESS | | filter |
# | filter | | | | mangle |
# | | | | | nat |
# -------------- --------- ---------------
#
#
# (Network) -------------------------[ mangle ]---------------------------------- --[ nat ]--
# | | --------------- --------- | | |
# mangle | | PREROUTING | | _exti | ------------ | | |
# PREROUTING | | EXT_IN-+-->| ALL-+-->| _extiall |-------------> RETURN | | |
# | | | | | | ------------ | | |
# nat | | | | | ------------ -------- | | |
# PREROUTING | | | | WEB-+-->| _extiweb |-+->| deny | | | |
# | | | | | | ------------ | | | | | |
# ------ | | | | | ------------ | | BAD1-+-> DROP | | |
# | | | | | | FTP-+-->| _extiftp |-+ | BAD2-+-> DROP | | |
# mangle mangle | | | | | ------------ | | BAD3-+-> DROP | | |
# INPUT FORWARD | | | | | ------------ | | BAD4-+-> DROP | | |
# | | | | | | EML-+-->| _extieml |-+ | BAD5-+-> DROP | | |
# filter filter | | | | | ------------ | | BAD6-+-> DROP | | |
# INPUT FORWARD | | | | | ------------ | | IP1-+-> DROP | | |
# | | | | | | OTHER-+-->| _extixxx |-+ | IP2-+-> DROP | | |
# [Local process] | | | | --------- ------------ | ---+---- | | |
# | | | | | --------- | | | | |
# | | | | INT_IN-+-->| _inti | | +-----> ACCEPT -+-->| |
# | | | --------------- |TO_LAN-+----------------|-----------> ACCEPT -+-->| |
# | | | | OTHER-+----------------+ | | |
# | | | --------- | | |
# | | --------------- --------- | | |
# | | | | POSTROUTING | | _exto | ------------ | | |
# mangle | | | EXT_OUT-+-->| ALL-+-->| _extoall |-------------> RETURN | | |
# OUTPUT | | | | | | ------------ | | |
# | | | | | | | ------------ | | |
# nat | | | | | WEB-+-->| _extoweb |-------------> ACCEPT -+-->| |
# OUTPUT | | | | | | ------------ | | |
# | | | | | | | ------------ | | |
# filter | | | | | FTP-+-->| _extoftp |-------------> ACCEPT -+-->| |
# OUTPUT | | | | | | ------------ | | |
# | | | | | | | ------------ | | |
# ------------------------ | | | | EML-+-->| _extoeml |-------------> ACCEPT -+-->| |
# | | | | | | ------------ | | |
# mangle | | | | | ------------ | | |
# POSTROUTING | | | | OTHER-+-->| _extoxxx |-------------> ACCEPT -+-->| |
# | | | | --------- ------------ | | |
# nat | | FROM_EXTIF-+----------------------------------------> ACCEPT -+-->| |
# POSTROUTING | | | --------- | | |
# | | | | | _into | | | |
# | | | INT_PROX-+-->| IP1-+----------------------------> ACCEPT -+-->| |
# (Network) | | EXT_NONPROX-+-->| IP2-+----------------------------> ACCEPT -+-->| |
# | --------------- --------- | | |
# --------------------------------------------------------------------- -----------
#
# ВНИМАНИЕ!
# * Только первый пакет из потока проходит через цепочки таблицы nat,
# трансляция адресов или маскарадинг применяются ко всем последующим пакетам в потоке автоматически.
# * Если в созданной цепочке заканчиваются правила, то пакет возвращается в родительскую цепочку
# (т.е. в конце цепочки "-j RETURN" писать не нужно).
# * Если в стандартной цепочке заканчиваются правила, то к пакету применяется политика цепочки.
#################################################################################################
# ПЕРЕМЕННЫЕ
#################################################################################################
PATH='/bin:/sbin:/usr/bin:/usr/sbin'; export PATH #
MESSAGES='/var/log/messages' # Лог-файл IPTables.
IPTABLESFILE='/etc/sysconfig/iptables' # Файл правил IPTables.
IPTFILE='/etc/sysconfig/ipt' # Файл с командами iptables.
LOCKFILE='/var/lock/subsys/fwtraf' # Файл блокировки.
CONFIGDIR='/etc/fwtraf' # Каталог с файлами конфигурации.
IPDBDIR='/var/log/ipdb' # Каталог ip-базы данных.
REPORTDIR='/var/www/fwtraf' # Каталог с отчетами о трафике.
STATICROUTES='/etc/sysconfig/static-routes' # Файл со статическими маршрутами
DHCPD_CONF='/etc/dhcpd.conf' # Файл конфигурации DHCPd.
CONFIGFILE="$CONFIGDIR/fwtraf.conf" # Файл конфигурации FWTraf.
REPORTFILE="$REPORTDIR/$(date +%Y-%m-%d).htm" # Файл отчета о трафике.
# DNSROOTDIR='/var/named/chroot'; [ -d "$DNSROOTDIR" ] || DNSROOTDIR='/' # Корневой каталог DNS.
DNSNAMESIG=''; [[ "$(named -v)" > 'BIND 9.2.4' ]] && DNSNAMESIG='check-names ignore; ' # Уст. опцию игн. проверку имён для новых версий BIND.
DG_CONF='/etc/dansguardian/dansguardian.conf' # Основной конфиг-файл DansGuardian.
DG_FGRP=`grep 2>/dev/null -aw ^filtergroups "$DG_CONF"|awk 'BEGIN{FS="="}{print $2}'` # Последняя группа фильтрации.
DG_FGRP=${DG_FGRP//[ \'\"]/} #
DG_FGRPLIST=`grep 2>/dev/null -aw ^filtergroupslist "$DG_CONF"|awk 'BEGIN{FS="="}{print $2}'` # Фильтруемые IP и соотв. им группы фильтрации.
DG_FGRPLIST=${DG_FGRPLIST//[ \'\"]/} #
DG_EXIPLIST=`grep 2>/dev/null -aw ^exceptioniplist "$DG_CONF"|awk 'BEGIN{FS="="}{print $2}'` # Нефильтруемые IP (группа 0).
DG_EXIPLIST=${DG_EXIPLIST//[ \'\"]/} #
LIMIT_EML='100' # Лимит для EMLSERVICES.
LIMIT_WEB='100' # Лимит для WEBSERVICES.
#################################################################################################
# ВСПОМОГАТЕЛЬНЫЕ ПЕРЕМЕННЫЕ
#################################################################################################
HOSTNAME=`hostname 2>/dev/null -s` # Имя хоста.
DOMAINNAME=`hostname 2>/dev/null -d` # Имя домена.
STATE='-m conntrack --ctstate' # Критерий iptables - ctstate.
_HOST_OR_NET='[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' # Критерий - хост или сеть.
_NET='[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/[0-9]*' # Критерий - сеть.
BLANK1='[ \t]\+' # Строка, содерж. минимум 1 пробел/таб.
BLANK0='[ \t]\?\+' # Строка, содерж. минимум 0 пробелов/табов.
N='[0-9]\+' # Строка, содерж. минимум 1 цифру.
LOGGED_TERM="$SSH_TTY"; [ "$LOGGED_TERM" ] || LOGGED_TERM=`tty 2>/dev/null` # Имя терминала, с которого запущен скрипт.
LOGGED_USER=`last 2>/dev/null -a|awk 2>/dev/null -v t=${LOGGED_TERM#/dev/} '{if ($2==t && $8=="logged") print $1 }'`
LOGGED_IP=`last 2>/dev/null -a|awk 2>/dev/null -v t=${LOGGED_TERM#/dev/} '{if ($2==t && $8=="logged") print $10}'`
#################################################################################################
# ФУНКЦИИ
#################################################################################################
lock_set() { echo>"$LOCKFILE" "locked by $LOGGED_USER ($LOGGED_IP)"; }
lock_run() { echo>"$LOCKFILE" "already running by $LOGGED_USER ($LOGGED_IP)"; }
lock_unset() { rm -f "$LOCKFILE"; }
lock_check() { local status=`cat 2>/dev/null "$LOCKFILE"`; [ "$status" ] && { printf "ERROR: $status\a\n"; exit 1; }; }
move_file() # (SRC_FILE,DST_FILE)
{
[ -a "$1" ] || return 1
[ -a "$2" ] && rm -f "$2"
mv -f "$1" "$2"
}
check_net() # (HOST_OR_NET) - Проверяет: это сеть или нет.
{
case "$1" in
'') return 3 ;;
0.*) return 2 ;;
${_NET}) return 0 ;;
*) return 1 ;;
esac
}
check_local() # (HOST_OR_NET) - Проверяет: это локальный IP/сеть или нет.
{
case "$1" in
'') return 2 ;;
10.*) return 0 ;;
172.16.*) return 0 ;;
192.168.*) return 0 ;;
*) return 1 ;;
esac
}
summa() # (DATEMASK,FILE) - Выводит суммарный трафик, соотв. указанной маске даты [YYYYMMDDHHMM].
{
cat 2>/dev/null "$2"|awk -v datemask="^$1" 'BEGIN{sum=0}{if ($1 ~ datemask) sum+=$2};END{CONVFMT="%.0f";printf "%s\n",sum}'
}
ip_or_net_valid() # (STRING) - Проверяет корректность IP или сети.
{
local ip=$1
ip=${ip/%\/[0-9]/}
ip=${ip/%\/[0-9][0-9]/}
[[ "${ip//[0-9]/}" != "..." ]] && return 1 # Выходим, если посторонние символы или нет трех точек.
[[ ".$ip." == *..* ]] && return 1 # Выходим, если не четыре элемента.
[[ ".$ip" == *.0[0-9]* ]] && return 1 # Выходим, если хотя бы один ведущий 0.
for i in ${ip//./ }; do # Разбиваем IP на четыре числа и проверяем каждое.
[ $i -gt 255 ] && return 1 # Выходим, если число больше 255.
done
return 0
}
ip() # (STRING) - Проверяет корректность и возвращает $IP.
{
IP='255.255.255.255'
ip_or_net_valid "$1" && IP="$1" || printf "\nERROR: \"$1\" - bad ip or net\a\n"
}
name() # (STRING) - Проверяет корректность и возвращает $NAME.
{
NAME='noname'
case "$1" in
[a-zA-Z0-9_-]*) NAME="$1" ;;
*) printf "\nERROR: \"$1\" - bad name\a\n" ;;
esac
}
prot() # (STRING) - Проверяет корректность и возвращает $PROT.
{
PROT='' # Возвращаемый протокол.
case "$1" in
tcp|udp|gre) PROT="-p $1" ;;
*) printf "\nERROR: \"$1\" - bad protocol\a\n" ;;
esac
}
ports() # (STRING) - Проверяет корректность и возвращает $PORTS,$SPORTS,$DPORTS,$DNAT_DPORT,$DNAT_TPORT.
{
SPORTS='' # Возвращаемые порты-источники.
DPORTS='' # Возвращаемые порты-назначения.
PORTS=`echo "$1"|sed -e "s/\/5443,48491/g;
s/\/14112/g;
s/\/9091/g;
s/\/1024,9443/g;
s/\/87/g;
s/\/3239/g;
s/\/7235/g;
s/\/613,614/g;
s/\/3411/g;
s/\/53/g;
s/\/25,110,143,587,995/g;
s/\/36789/g;
s/\/50025,50110/g;
s/\/20,21/g;
s/\/69/g;
s/\/2226/g;
s/\/80/g;
s/\/443/g;
s/\/5190/g;
s/\/143/g;
s/\/6667/g;
s/\/5222,5223/g;
s/\/1433,1434/g;
s/\/123/g;
s/\/81/g;
s/\/1521/g;
s/\/110/g;
s/\/995/g;
s/\/1723/g;
s/\/5750,9999,15100/g;
s/\/4899/g;
s/\/3389/g;
s/\/873/g;
s/\/5060/g;
s/\/137,138,139/g;
s/\/25/g;
s/\/2525/g;
s/\/587/g;
s/\/161,162/g;
s/\/22/g;
s/\/3128/g;
s/\/23/g;
s/\/6881,6882,6883,6884,6885,6886,6887,6888,6889/g;
s/\/33434:33459/g;
s/\/$WEBPORT,443/g;
s/\/8088,8089/g;
s/\/10000/g;
s/\/2802/g;
s/!/! /g"`
DNAT_DPORT=`echo "$PORTS"|sed -e "s/all//; s/[0-9:]\+,//g; s/^[0-9:]\+$//g; s/! $N//g"|cut -d'-' -f1`
DNAT_TPORT=`echo "$PORTS"|sed -e "s/all//; s/,[0-9:]\+//g; s/^[0-9:]\+$//g; s/! $N//g"|cut -d'-' -f2`
PORTS=${PORTS//-/,} # Замещает все вхождения "-" строкой ",".
case "$PORTS" in
all|'') return ;; # Все порты/нет портов.
[^0-9!]*|*[^0-9!]) printf "\nERROR: \"$1\" - bad ports\a\n"; return ;; # Неправильные порты.
[0-9]*,[0-9]*) SPORTS="-m multiport --sports $PORTS"; DPORTS="-m multiport --dports $PORTS"; return ;; # Несколько портов.
'! '[0-9]*|[0-9]*) SPORTS="--sport $PORTS" ; DPORTS="--dport $PORTS" ; return ;; # Кроме порта/один порт.
*) printf "\nERROR: \"$1\" - bad ports\a\n"; return ;; # Неправильные порты.
esac
}
limit() # (STRING) - Проверяет корректность и возвращает $LIMIT.
{
LIMIT='' # Возвращаемый лимит.
case "$1" in
'') ;;
[0-9]*) LIMIT="-m limit --limit $1/s" ;;
*) printf "\nERROR: \"$1\" - bad limit\a\n" ;;
esac
}
conn_limit() # (STRING) - Проверяет корректность и возвращает $CONN_LIMIT - макс. число подключений в минуту.
{
CONN_LIMIT='' # Возвращаемый лимит.
case "$1" in
'') ;;
[0-9]*) CONN_LIMIT="$1" ;;
*) printf "\nERROR: \"$1\" - bad conn_limit\a\n" ;;
esac
}
wa() # (STRING) - Проверяет корректность и возвращает $WA.
{
WA='' # Возвращаемый web-доступ.
case "$1" in
'') WA='' ;;
[0-9]) WA="$1" ;;
*) printf "\nERROR: \"$1\" - bad web access group\a\n" ;;
esac
}
function forwarders() # () - Ищем внешние DNS-сервера в /etc/resolv.conf и выводим.
{
cat 2>/dev/null '/etc/resolv.conf' \
|awk '{if ($1=="nameserver" && $2!~/127\.0\.0\./ && $2~/[0-9]/) forwarders=forwarders$2"; "};
END{if (forwarders!="") printf " forwarders { %s};\n",forwarders}'
}
write_dns_cfg_head() # () - Устанавливаем флаг начала и пишем его заголовок.
{
F_DNS_CFG='Y'
cat>"$DNSROOTDIR/etc/named.conf"<<*
options { directory "/var/named/";
allow-query {"trusted";};
allow-transfer {"trusted";};
allow-recursion {"trusted";};
$(forwarders)
// * If there is a firewall between you and nameservers you want to talk to, you might need to uncomment
// * the query-source directive below. Previous versions of BIND always asked questions using port 53,
// * but BIND 8.1 uses an unprivileged port by default.
// query-source address * port 53;
};
acl "trusted" { 127.0.0.1; 10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16; };
include "/etc/rndc.key";
#controls { inet 127.0.0.1 allow {localhost;} keys {rndckey;}; };
zone "." { type hint ; file "named.ca"; };
zone "$DOMAINNAME" { type master; file "$DOMAINNAME.zone"; $DNSNAMESIG};
zone "localdomain" IN { type master; file "localdomain.zone"; allow-update {none;}; };
zone "localhost" { type master; file "localhost.zone" ; allow-update {none;}; };
zone "0.0.127.in-addr.arpa" { type master; file "named.local" ; allow-update {none;}; };
zone "255.in-addr.arpa" IN { type master; file "named.broadcast" ; allow-update {none;}; };
*
}
write_dns_z_head() # (ZONE) - Пишем заголовок прямой или обратной зоны.
{
cat>"$DNSROOTDIR/var/named/$1.zone"<<*
;TTL - Time To Live (время жизни записей).
;SOA - marks of start of zone of authority (начало полномочий).
;@ - имя зоны.
\$TTL 86400
@ IN SOA @ root.localhost. (
2002112100 ; Serial
28800 ; Refresh
7200 ; Retry
604800 ; Expire
86400 ; TTL
)
@ IN NS 127.0.0.1 ; Name Server для зоны
@ IN MX 0 127.0.0.1 ; Mail eXchanger для зоны
*
}
write_dns_rz_head() # (RZONE,IPN3,IPN2,IPN1) - Пишем заголовок обратной DNS-зоны, описываем ее в конфиг.файле.
{
let F_DNS_RZ_${2}_${3}_${4}='Y' # Устанавливаем флаг начала зоны,
write_dns_z_head "$1" # пишем заголовок обратной зоны.
printf>>"$DNSROOTDIR/etc/named.conf" "zone %30s { type master; file %31s; $DNSNAMESIG};\n" \"$1\" \"$1.zone\" # Дописываем конфиг.файл DNS.
}
write_dns_dz_head() # (DZONE) - Устанавливаем флаг начала прямой зоны и пишем ее заголовок.
{
F_DNS_DZ='Y' # Устанавливаем флаг начала зоны,
write_dns_z_head "$1" # пишем заголовок прямой зоны.
}
write_dns_edz_head() # (EDZONE,NAME) - Устанавливаем флаг начала прямой внешней зоны и пишем ее заголовок.
{
let F_DNS_EDZ_${2}='Y' # Устанавливаем флаг начала зоны,
write_dns_z_head "$1" # пишем заголовок прямой зоны.
printf>>"$DNSROOTDIR/etc/named.conf" "zone %30s { type master; file %31s; $DNSNAMESIG};\n" \"$1\" \"$1.zone\" # Дописываем конфиг.файл DNS.
}
write_dns() # (IP,NAME) - Пишем хост в зоны DNS.
{
[ -d "$DNSROOTDIR" ] || return # Если каталог не задан или не существует.
check_net "$1" && return # Если это сеть.
check_local "$1" || return # Если это не локальный IP.
local -a IPN=(${1//./ })
local IPN1=${IPN[0]}
local IPN2=${IPN[1]}
local IPN3=${IPN[2]}
local IPN4=${IPN[3]}
local RZ="$IPN3.$IPN2.$IPN1.in-addr.arpa" # Имя обратной зоны.
local DZ="$DOMAINNAME" # Имя прямой зоны.
eval local F_DNS_RZ=\${F_DNS_RZ_${IPN3}_${IPN2}_${IPN1}}
[ "${F_DNS_CFG}" ] || write_dns_cfg_head # Если в конфиг.файл DNS еще не писали.
[ "${F_DNS_DZ}" ] || write_dns_dz_head "$DZ" # Если в прямую DNS-зону еще не писали.
[ "${F_DNS_RZ}" ] || write_dns_rz_head "$RZ" "$IPN3" "$IPN2" "$IPN1" # Если в эту обратную DNS-зону еще не писали.
printf>>"$DNSROOTDIR/var/named/$DZ.zone" '%-25s IN A %s\n' "$2" "$1" # Дописываем прямую DNS-зону.
printf>>"$DNSROOTDIR/var/named/$RZ.zone" '%-25s IN PTR %s\n' $IPN4 "$2.$DZ." # Дописываем обратную DNS-зону.
[ "$2" == 'kms' ] && \
printf>>"$DNSROOTDIR/var/named/$DZ.zone" '%-25s IN SRV 0 0 1688 %s\n' '_vlmcs._tcp' "$2" # Дописываем SRV-запись в прямую DNS-зону.
[ "$EXTDOMAINFLAG" ] || return # Проверяем, нужно ли писать в зону внешнего домена.
[ "$EXTDOMAINNAME" ] || return # Проверяем, указан ли внешний домен.
local EDZ="$2.$EXTDOMAINNAME" # Имя прямой зоны внешнего домена.
eval local F_DNS_EDZ=\${F_DNS_EDZ_${2}}
[ "${F_DNS_EDZ}" ] || write_dns_edz_head "$EDZ" "$2" # Если в прямую внешнюю DNS-зону еще не писали.
printf>>"$DNSROOTDIR/var/named/$EDZ.zone" '%-25s IN A %s\n' '@' "$1" # Дописываем прямую внешнюю DNS-зону.
}
write_dg_exiplist_head() # () - Устанавливаем флаг начала exceptioniplist и очищаем его.
{
F_DG_EXIPLIST='Y' # Устанавливаем флаг начала файла.
:>"$DG_EXIPLIST.tmp" # Очищаем временный файл exceptioniplist.
}
write_dg_fgrplist_head() # () - Устанавливаем флаг начала filtergroupslist и очищаем его.
{
F_DG_FGRPLIST='Y' # Устанавливаем флаг начала файла.
:>"$DG_FGRPLIST.tmp" # Очищаем временный файл filtergroupslist.
}
write_dg() # (IP,GROUP_NUM) - Пишем IP и номер фильтрующей группы GROUP_NUM в файл filtergroupslist.
{
[[ "$WEBPROXY" == 'DGSQUID' ]] || return # Если не используется DansGurdian.
[[ "$1" == ${_NET} ]] && return # Если это сеть.
case "$2" in
'') return # WEB-доступ: нет группы.
;;
0) [ "$DG_EXIPLIST" ] || return # WEB-доступ: нефильтруемый.
[ "${F_DG_EXIPLIST}" ] || write_dg_exiplist_head # Если в exceptioniplist еще не писали, то создаем его.
echo>>"$DG_EXIPLIST.tmp" "$1" # Дописываем временный файл exceptioniplist.
;;
*) [ "$DG_FGRPLIST" ] || return # WEB-доступ: фильтруемый в соотв. с номером группы.
[ "${F_DG_FGRPLIST}" ] || write_dg_fgrplist_head # Если в filtergroupslist еще не писали, то создаем его.
echo>>"$DG_FGRPLIST.tmp" "$1=filter$2" # Дописываем временный файл filtergroupslist.
;;
esac
}
write_ipdb() # (IP) - Пишем информацию в ip-базу данных.
{
add_uniqstr() # (FILE,STR) - Дописываем уникальную строку, время игнорируем.
{
local file="$1"
local str=`echo $2` # Удаляем пробелы в начале и в конце.
[ "$file" ] || return
[ "$str" ] || return
cat 2>/dev/null "$file"|grep -av "^.* $str\$">"/tmp/fwtraf.add_uniqstr.$$"
move_file "/tmp/fwtraf.add_uniqstr.$$" "$file"
echo>>"$file" "$DATE $str"
}
local ip="${1/\/*}"
[[ "$IPDBDIR" ]] || return # Если каталог не задан.
check_local "$ip" || return # Если это не локальный IP.
declare local line=`sed -n "/^${BLANK0}[ad]${BLANK1}.*${ip}[\/[0-9]\+]\?${BLANK1}/p" $CONFIGFILE|sed -e 's/^#//p'|sed q`; [ "$line" ] || return
declare -a local a_line=( ${line%% #*} )
declare local cmd=' '; [[ "${a_line[0]}" == [ad] ]] && cmd=${a_line[0]}
declare local name=' '; [[ "${a_line[2]}" == [0-9a-zA-Z_-]* ]] && name=${a_line[2]}
declare local wa=' '; [[ "${a_line[3]}" == [0-9]* ]] && wa=${a_line[3]}
declare local ports=' '; [[ "${a_line[4]}" == [0-9a-z!]* ]] && ports=${a_line[4]}
declare local limit=' '; [[ "${a_line[5]}" == [0-9]* ]] && limit=${a_line[5]}
declare local desc=' '; [[ "${line/*#/}" > ' ' ]] && desc="${line/*#/}"
declare local DATE="$(date +%Y%m%d%H%M)"
mkdir -p "$IPDBDIR/$ip"
add_uniqstr "$IPDBDIR/$ip/fwtraf_name" "$name"
add_uniqstr "$IPDBDIR/$ip/fwtraf_access" "$cmd $ports $wa $limit"
add_uniqstr "$IPDBDIR/$ip/fwtraf_desc" "$desc"
}
ipt_begin() # () - Начинаем запись команд iptables в файл $IPTFILE.tmp.
{
echo>"$IPTFILE.tmp" '#!/bin/bash'
}
ipt() # (RULES...) - Пишем команды iptables в файл $IPTFILE.tmp.
{
echo>>"$IPTFILE.tmp" "iptables $@"
}
ipt_end() # () - Применяем команды iptables из файла $IPTFILE.tmp.
{
printf '\n'
[ -a "$IPTFILE.tmp" ] || return
diff &>/dev/null "$IPTFILE" "$IPTFILE.tmp" && { rm -f "$IPTFILE.tmp"; return; }
move_file "$IPTFILE" "$IPTFILE.old"
move_file "$IPTFILE.tmp" "$IPTFILE"
printf '[ save traffic counters ]\n'; trafhourly # Сохраняем трафик, т.к. сейчас цепочки будут созданы заново.
printf '[ all rules apply ]\n' ; time nice -n -20 bash -c ". $IPTFILE"
}
dg_begin() # () - Сохраняем списки DG, чтобы потом узнать, были ли в них изменения.
{
[ "$WEBPROXY" == 'DGSQUID' ] || return # Если не используется DansGurdian.
[ "$DG_EXIPLIST" ] && :>"$DG_EXIPLIST.tmp" # Очищаем временный файл exceptioniplist.
}
dg_end() # () - Перезапускаем DG, если были изменения.
{
printf '\n'
[ "$WEBPROXY" == 'DGSQUID' ] || return # Если не используется DansGurdian.
[ -a "$DG_EXIPLIST" ] || return # Если не существует файл exceptioniplist.
[ -a "$DG_FGRPLIST" ] || return # Если не существует файл filtergroupslist.
local dg_restart=''
if [ -a "$DG_EXIPLIST.tmp" ]; then
diff &>/dev/null "$DG_EXIPLIST" "$DG_EXIPLIST.tmp"
if [ $? -eq 0 ]; then
rm -f "$DG_EXIPLIST.tmp"
else
dg_restart='Y'
move_file "$DG_EXIPLIST" "$DG_EXIPLIST.old"
move_file "$DG_EXIPLIST.tmp" "$DG_EXIPLIST"
fi
fi
if [ -a "$DG_FGRPLIST.tmp" ]; then
diff &>/dev/null "$DG_FGRPLIST" "$DG_FGRPLIST.tmp"
if [ $? -eq 0 ]; then
rm -f "$DG_FGRPLIST.tmp"
else
dg_restart='Y'
move_file "$DG_FGRPLIST" "$DG_FGRPLIST.old"
move_file "$DG_FGRPLIST.tmp" "$DG_FGRPLIST"
fi
fi
if [ "$dg_restart" ]; then
[ "$WEBPROXY" == "DGSQUID" ] && $NICE service dansguardian restart # Перезапускаем DansGuardian.
fi
}
dnat() # (IP,DPORT,TPORT) - Перенаправляем внешний входящий tcp-трафик с $IF_EXT:$DPORT на $IP:$TPORT.
{
ip "$1" # Получаем $IP
ipt -t nat -A PREROUTING -p tcp -i $IF_EXT --dport $2 -d $IP_EXT -j DNAT --to-destination $1:$3
ipt -t filter -A FORWARD -p tcp -i $IF_EXT --dport $3 -j ACCEPT
ipt -t filter -A FORWARD -p tcp -s $IP $STATE ESTABLISHED,RELATED -j ACCEPT # Установленные соединения с IP.
ipt -t filter -A FORWARD -p tcp -d $IP $STATE ESTABLISHED,RELATED -j ACCEPT # Установленные соединения к IP.
# ipt -t nat -A POSTROUTING -p tcp -o $IF_EXT -s $1 -j SNAT --to-source $IP_EXT
# ipt -t nat -A POSTROUTING -p tcp -o $IF_EXT --dport $3 -s $1 -j SNAT --to-source $IP_EXT
printf '-'
}
i() # (PROT,PORTS,LIMIT) - Разрешаем порты/протоколы c лимитом для внутренней сети.
{
[ "$ENABLE_IEC" ] || return # Проверяем, разрешено ли исполнять команду.
prot "$1"; ports "$2"; limit "$3"; conn_limit "$4" # Получаем $PROT; $PORTS,$SPORTS,$DPORTS,DNAT_DPORT,$DNAT_TPORT; $LIMIT; $CONN_LIMIT.
if [ "$CONN_LIMIT" ]; then
CONN_NAME=$((CONN_NAME+1))
ipt -t filter -A INPUT $PROT $DPORTS -i $IFs_INT $STATE NEW -m recent --name i$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j LOG --log-prefix "fwtraf_i$CONN_NAME:"
ipt -t filter -A INPUT $PROT $DPORTS -i $IFs_INT $STATE NEW -m recent --name i$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j DROP
ipt -t filter -A INPUT $PROT $DPORTS -i $IFs_INT $STATE NEW -m recent --name i$CONN_NAME --set
fi
for lan in $LANS; do
ipt -t filter -A INPUT $PROT $DPORTS -i $IFs_INT -d $lan $LIMIT -j ACCEPT
ipt -t filter -A INPUT $PROT $SPORTS -i $IFs_INT -d $lan $LIMIT -j ACCEPT
# ipt -t filter -A OUTPUT $PROT $DPORTS -s $lan -o $IFs_INT $LIMIT -j ACCEPT
ipt -t filter -A OUTPUT $PROT $SPORTS -s $lan -o $IFs_INT $LIMIT -j ACCEPT
done
ipt -t filter -A FORWARD $PROT $DPORTS -i $IFs_INT -o $IFs_INT $LIMIT -j ACCEPT
ipt -t filter -A FORWARD $PROT $SPORTS -i $IFs_INT -o $IFs_INT $LIMIT -j ACCEPT
# Для доступа к внешнему интерфейсу из LAN.
ipt -t filter -A INPUT $PROT $DPORTS -i $IFs_INT -d $IP_EXT $LIMIT -j ACCEPT
ipt -t filter -A INPUT $PROT $SPORTS -i $IFs_INT -d $IP_EXT $LIMIT -j ACCEPT
# ipt -t filter -A OUTPUT $PROT $DPORTS -s $IP_EXT -o $IFs_INT $LIMIT -j ACCEPT
ipt -t filter -A OUTPUT $PROT $SPORTS -s $IP_EXT -o $IFs_INT $LIMIT -j ACCEPT
printf 'i'
}
e() # (PROT,PORTS,LIMIT) - Разрешаем порты/протоколы c лимитом для внешней сети.
{
[ "$ENABLE_IEC" ] || return # Проверяем, разрешено ли исполнять команду.
prot "$1"; ports "$2"; limit "$3"; conn_limit "$4" # Получаем $PROT; $PORTS,$SPORTS,$DPORTS,DNAT_DPORT,$DNAT_TPORT; $LIMIT; $CONN_LIMIT.
if [ "$CONN_LIMIT" ]; then
CONN_NAME=$((CONN_NAME+1))
ipt -t filter -A INPUT $PROT $DPORTS -i $IF_EXT $STATE NEW -m recent --name e$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j LOG --log-prefix "fwtraf_e$CONN_NAME:"
ipt -t filter -A INPUT $PROT $DPORTS -i $IF_EXT $STATE NEW -m recent --name e$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j DROP
ipt -t filter -A INPUT $PROT $DPORTS -i $IF_EXT $STATE NEW -m recent --name e$CONN_NAME --set
fi
ipt -t filter -A INPUT $PROT $DPORTS -i $IF_EXT $LIMIT -j ACCEPT
ipt -t filter -A INPUT $PROT $SPORTS -i $IF_EXT $LIMIT -j ACCEPT
ipt -t filter -A OUTPUT $PROT $DPORTS -o $IF_EXT $LIMIT -j ACCEPT
ipt -t filter -A OUTPUT $PROT $SPORTS -o $IF_EXT $LIMIT -j ACCEPT
printf 'e'
}
c() # (PROT,PORTS,LIMIT) - Разрешаем порты/протоколы c лимитом для внутренней и внешней сетей.
{
[ "$ENABLE_IEC" ] || return # Проверяем, разрешено ли исполнять команду.
prot "$1"; ports "$2"; limit "$3"; conn_limit "$4" # Получаем $PROT; $PORTS,$SPORTS,$DPORTS,DNAT_DPORT,$DNAT_TPORT; $LIMIT; $CONN_LIMIT.
if [ "$CONN_LIMIT" ]; then
CONN_NAME=$((CONN_NAME+1))
ipt -t filter -A INPUT $PROT $DPORTS $STATE NEW -m recent --name c$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j LOG --log-prefix "fwtraf_c$CONN_NAME:"
ipt -t filter -A INPUT $PROT $DPORTS $STATE NEW -m recent --name c$CONN_NAME --update --seconds 60 --hitcount $CONN_LIMIT -j DROP
ipt -t filter -A INPUT $PROT $DPORTS $STATE NEW -m recent --name c$CONN_NAME --set
fi
ipt -t filter -A INPUT $PROT $DPORTS $LIMIT -j ACCEPT
[ "$SPORTS" ] && ipt -t filter -A INPUT $PROT $SPORTS $LIMIT -j ACCEPT
ipt -t filter -A OUTPUT $PROT $DPORTS $LIMIT -j ACCEPT
[ "$SPORTS" ] && ipt -t filter -A OUTPUT $PROT $SPORTS $LIMIT -j ACCEPT
ipt -t filter -A FORWARD $PROT $DPORTS $LIMIT -j ACCEPT
[ "$SPORTS" ] && ipt -t filter -A FORWARD $PROT $SPORTS $LIMIT -j ACCEPT
[ "$SNAT" ] && [ "$PROT" != 'gre' ] && \
for lan in $LANS; do
ipt -t nat -A POSTROUTING $PROT $DPORTS -s $lan -o $IF_EXT -j SNAT --to-source $IP_EXT
done
printf 'c'
}
count_ip() # (IP) - Считаем трафик для IP-адреса хоста или сети.
{
check_local "$1" || return # Если это не локальный IP.
ipt -t mangle -A _into -d $1 -j ACCEPT # Если это локальный хост, то учитываем внешний входящий трафик.
}
allow_ip() # (IP) - Разрешаем tcp-трафик для IP (а также udp-трафик, если не заданы порты).
{
[ "$DPORTS" ] && PROT='-p tcp' || PROT=''
ipt -t filter -A INPUT $PROT -s $1 $DPORTS $LIMIT -j ACCEPT # Разрешаем входящий tcp-трафик для портов от клиента к серверу.
ipt -t filter -A FORWARD $PROT -s $1 $DPORTS $LIMIT -j ACCEPT # Разрешаем tcp-трафик для портов от клиента через сервер.
ipt -t filter -A OUTPUT $PROT -d $1 $LIMIT -j ACCEPT # Режем скорость отдачи пакетов сервером клиенту.
[ "$SNAT" ] && \
ipt -t nat -A POSTROUTING $PROT -s $1 $DPORTS -o $IF_EXT $LIMIT -j SNAT --to-source $IP_EXT # Разрешаем SNAT для трафика, стремящегося наружу.
}
allow_tcpservice() # (IP,PORTS,LIMIT) - Разрешаем обращения к внешним сервисам (ip,tcp-портам) для всей внутренней сети.
{
ip "$1"; ports "$2"; limit "$3" # Получаем $IP; $PROT; $PORTS; $LIMIT.
ipt -t nat -A PREROUTING -p tcp -i $IFs_INT $DPORTS -d $IP $LIMIT -j ACCEPT
ipt -t filter -A FORWARD -p tcp -i $IFs_INT $DPORTS -d $IP $LIMIT -j ACCEPT
[ "$SNAT" ] && \
for lan in $LANS; do
ipt -t nat -A POSTROUTING -p tcp -o $IF_EXT $DPORTS -s $lan -d $IP $LIMIT -j SNAT --to-source $IP_EXT
done
printf '@'
}
deny_ip() # (IP) - Запрещаем tcp/udp-трафик для IP.
{
ipt -t mangle -A deny -p tcp -s $1 $DPORTS -j DROP # Запрещаем весь входящий tcp-трафик с IP.
ipt -t mangle -A deny -p tcp -s $1 $SPORTS -j DROP # Запрещаем весь входящий tcp-трафик с IP.
ipt -t mangle -A deny -p udp -s $1 $DPORTS -j DROP # Запрещаем весь входящий udp-трафик с IP.
ipt -t mangle -A deny -p udp -s $1 $SPORTS -j DROP # Запрещаем весь входящий udp-трафик с IP.
}
deny_ip_all() # (IP) - Запрещаем весь tcp/udp-трафик для IP.
{
ipt -t mangle -A deny -s $1 -j DROP # Запрещаем весь входящий tcp/udp-трафик с IP.
}
d() # (IP,NAME,WA,PORTS) - Запрещаем весь входящий трафик для IP.
{
[ "$ENABLE_D" ] || return # Проверяем, разрешено ли исполнять команду.
ip "$1"; name "$2"; wa "$3"; ports "$4" # Получаем $IP; $NAME; $WA; $PORTS,$SPORTS,$DPORTS,DNAT_DPORT,$DNAT_TPORT.
case "$PORTS" in
'') write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
all) deny_ip_all "$IP" # Запрещаем весь tcp/udp-трафик для IP.
write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
*) deny_ip "$IP" # Запрещаем tcp/udp-трафик для IP.
count_ip "$IP" # Считаем трафик для IP.
write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_dg "$IP" "$WA" # Определяем права WEB-доступа.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
esac
printf 'd'
}
a() # (IP,NAME,WA,PORTS,LIMIT) - Разрешаем tcp-порты для IP хоста/сети, определяем группу WEB-доступа, устанавливаем лимит.
{
[ "$ENABLE_A" ] || return # Проверяем, разрешено ли исполнять команду.
ip "$1"; name "$2"; wa "$3"; ports "$4"; limit "$5" # Получаем $IP; $NAME; $WA; $PORTS,$SPORTS,$DPORTS,DNAT_DPORT,$DNAT_TPORT; $LIMIT.
case "$PORTS" in
'') write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
all) allow_ip "$IP" # Разрешаем порты для IP, устанавливаем лимит.
count_ip "$IP" # Считаем трафик для IP.
write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_dg "$IP" "$WA" # Определяем права WEB-доступа.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
*) allow_ip "$IP" # Разрешаем порты для IP, устанавливаем лимит.
count_ip "$IP" # Считаем трафик для IP.
[ "$DNAT_DPORT" ] && [ "$DNAT_TPORT" ] && dnat "$IP" "$DNAT_DPORT" "$DNAT_TPORT"
write_dns "$IP" "$NAME" # Прописываем в DNS, если адрес из локальной сети.
write_dg "$IP" "$WA" # Определяем права WEB-доступа.
write_ipdb "$IP" # Пишем информацию в ip-базу данных, если адрес из локальной сети.
;;
esac
printf 'a'
}
D() # (IP,NAME,WA,PORTS) - Запрещаем весь входящий трафик для IP.
{
EXTDOMAINFLAG='Y' # Уст. флаг записи в зону внешнего домена.
d $1 $2 $3 $4
EXTDOMAINFLAG='' # Сбрасываем флаг записи в зону внешнего домена.
}
A() # (IP,NAME,WA,PORTS,LIMIT) - Разрешаем tcp-порты для IP хоста/сети, определяем группу WEB-доступа, устанавливаем лимит.
{
EXTDOMAINFLAG='Y' # Уст. флаг записи в зону внешнего домена.
a $1 $2 $3 $4 $5
EXTDOMAINFLAG='' # Сбрасываем флаг записи в зону внешнего домена.
}
enable_gw() # () - Включаем маршрутизацию/NAT через внутренний шлюз к сетям.
{
[ "$NETS_VIA_GW" ] || NETS_VIA_GW=`cat 2>/dev/null "$STATICROUTES"|grep -a '.*/.*'|awk '{print $3}'`
# Удаляем из STATICROUTES добавленные ранее сети.
cat 2>/dev/null "$STATICROUTES"|grep -av '.*/.*'>"/tmp/fwtraf.enable_gw.$$"
move_file "/tmp/fwtraf.enable_gw.$$" "$STATICROUTES"
chmod 644 "$STATICROUTES"
chown root:root "$STATICROUTES"
# Удаляем сети, и если задан шлюз GW, добавляем их снова в таблицу маршрутизации и в STATICROUTES.
for net in $NETS_VIA_GW; do
route 2>/dev/null del -net $net
[ "$GW" ] || continue
printf "Add route to $net via $GW"
route 2>/dev/null add -net $net gw $GW
if [ $? -eq 0 ]; then
# Определяем интерфейс, через который подключен шлюз.
local if_to_gw=`route -n|grep -a "^${net%%\/*} "|awk '{print $8}'`
# Добавляем в STATICROUTES сеть.
echo>>"$STATICROUTES" "$if_to_gw net $net gw $GW"
# Разрешаем пакеты через шлюз к сетям.
ipt -t mangle -A PREROUTING -i $IFs_INT -d $net -j ACCEPT
for lan in $LANS; do
ipt -t mangle -A POSTROUTING -s $lan -d $net -j ACCEPT
done
# Разрешаем пакеты конкретно на шлюз (нужно только для его контроля).
ipt -t mangle -A PREROUTING -i $IFs_INT -d $GW -j ACCEPT
for lan in $LANS; do
ipt -t mangle -A POSTROUTING -s $lan -d $GW -j ACCEPT
done
[ "$SNAT_TO_GW" ] || { echo; continue; }
echo ". Enable SNAT to $net on $SNAT_TO_GW"
for lan in $LANS; do
ipt -t nat -A POSTROUTING -s $lan -d $net -j SNAT --to-source $SNAT_TO_GW
ipt -t nat -A POSTROUTING -s $lan -d $GW -j SNAT --to-source $SNAT_TO_GW
done
else
echo ': Error'
fi
done
}
fwprepare() # (POLICY) - Подготавливает IPTables.
{
# Задаем политики на цепочки.
ipt -t mangle -P PREROUTING ACCEPT; ipt -t filter -P INPUT $1; ipt -t nat -P PREROUTING ACCEPT
ipt -t mangle -P OUTPUT ACCEPT; ipt -t filter -P FORWARD $1; ipt -t nat -P OUTPUT ACCEPT
ipt -t mangle -P POSTROUTING ACCEPT; ipt -t filter -P OUTPUT $1; ipt -t nat -P POSTROUTING ACCEPT
# Удаляем все правила и очищаем цепочки.
ipt -t mangle -F; ipt -t mangle -X
ipt -t filter -F; ipt -t filter -X
ipt -t nat -F; ipt -t nat -X
# Разрешаем трафик с петлевого интерфейса.
ipt -t mangle -A PREROUTING -i $IF_LO -j ACCEPT; ipt -t filter -A INPUT -i $IF_LO -j ACCEPT # входящий.
ipt -t mangle -A POSTROUTING -o $IF_LO -j ACCEPT; ipt -t filter -A OUTPUT -o $IF_LO -j ACCEPT # исходящий.
# Загружаем модули.
depmod -a
modprobe &>/dev/null ip_conntrack
modprobe &>/dev/null ip_conntrack_ftp ports=21,2121
modprobe &>/dev/null ip_nat_ftp ports=21,2121
modprobe &>/dev/null ip_nat_pptp
modprobe &>/dev/null ip_conntrack_pptp
modprobe &>/dev/null ip_gre
echo>'/proc/sys/net/ipv4/ip_conntrack_max' '131072'
}
fwaccept() # () - Разрешаем все пакеты, отключаем SNAT.
{
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
ipt_begin # Начинаем запись команд iptables в файл $IPTFILE.
fwprepare ACCEPT
ipt_end # Применяем команды iptables из файла $IPTFILE.
lock_unset # Удаляем блокировку запуска.
}
fwsimple() # () - Устанавливает простые правила для всех локалых сетей.
{
[ "$IF_EXT" ] || { printf 'ERROR: external interface not found\a\n'; exit 1; }
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
ipt_begin # Начинаем запись команд iptables в файл $IPTFILE.
fwprepare ACCEPT
enable_gw # Включаем маршрутизацию/NAT через внутренний шлюз к сетям.
# Перенаправляем http на Squid/DansGuardian.
[ "$WEBPROXY" == 'SQUID' ] && ipt -t nat -A PREROUTING -p tcp -i $IFs_INT --dport 80 -j REDIRECT --to-ports 3128
[ "$WEBPROXY" == 'SQUID' ] && ipt -t nat -A PREROUTING -p tcp -i $IFs_INT --dport 8080 -j REDIRECT --to-ports 3128
[ "$WEBPROXY" == 'DGSQUID' ] && ipt -t nat -A PREROUTING -p tcp -i $IFs_INT --dport 80 -j REDIRECT --to-ports 8080
[ "$SNAT" ] && \
{
# Запрещаем NAT для SMTP.
ipt -t nat -A POSTROUTING -p tcp -o $IF_EXT --dport 25 -j DROP
for lan in $LANS; do
[ "$REMOTE_LANS" ] && \
for remote_lan in $REMOTE_LANS; do
ipt -t nat -A POSTROUTING -s $lan -d $remote_lan -j ACCEPT
done
ipt -t nat -A POSTROUTING -s $lan -o $IF_EXT -j SNAT --to-source $IP_EXT
done
}
ipt_end # Применяем команды iptables из файла $IPTFILE.
lock_unset # Удаляем блокировку запуска.
}
fwsingle() # (IP) - Устанавливает простые правила для одного локального IP (опасно).
{
ip "$1" # Получаем $IP
[ "$IP" ] || { printf 'ERROR: local IP not specified\a\n' ; exit 1; }
[ "$IF_EXT" ] || { printf 'ERROR: external interface not found\a\n'; exit 1; }
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
ipt_begin # Начинаем запись команд iptables в файл $IPTFILE.
fwprepare ACCEPT
enable_gw # Включаем маршрутизацию/NAT через внутренний шлюз к сетям.
[ "$SNAT" ] && \
{
# Запрещаем NAT для SMTP.
ipt -t nat -A POSTROUTING -p tcp -o $IF_EXT --dport 25 -j DROP
[ "$REMOTE_LANS" ] && \
for remote_lan in $REMOTE_LANS; do
ipt -t nat -A POSTROUTING -s $IP -d $remote_lan -j ACCEPT
done
ipt -t nat -A POSTROUTING -s $IP -o $IF_EXT -j SNAT --to-source $IP_EXT
}
ipt_end # Применяем команды iptables из файла $IPTFILE.
lock_unset # Удаляем блокировку запуска.
}
fwnormal() # () - Устанавливает правила для нормальной работы сервера.
{
[ "$HOSTNAME" ] || { printf 'ERROR: host name unknown - check /etc/hosts\a\n' ; exit 1; }
[ "$DOMAINNAME" ] || { printf 'ERROR: domain name unknown - check /etc/hosts\a\n'; exit 1; }
[ "$IF_EXT" ] || { printf 'ERROR: external interface not found\a\n' ; exit 1; }
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
dg_begin # Сохраняем списки DG, чтобы потом узнать, были ли в них изменения.
ipt_begin # Начинаем запись команд iptables в файл $IPTFILE.
printf '\n[ base rules processing ]\n'; fwprepare DROP # Подготавливаем IPTables.
################################### Правила, в которые попадает больше всего трафика,
### Цепочки (таблица mangle) ### ставим повыше для увеличения скорости и снижения нагрузки на CPU).
###################################
# # Маркируем внешний трафик (Type Of Service: 0x02 - Minimize Cost).
# ipt -t mangle -A PREROUTING -i $IF_EXT -j TOS --set-tos 0x02
# ipt -t mangle -A PREROUTING -i $IF_EXT -j MARK --set-mark 0x02
############################################################################
### Цепочка и правила для отсева ненужных пакетов - (таблица mangle) ###
############################################################################
ipt -t mangle -N deny # Создаем цепочку для отсева ненужных пакетов.
ipt -t mangle -A deny -p tcp --tcp-flags SYN,ACK SYN,ACK $STATE NEW -j DROP
ipt -t mangle -A deny -p tcp ! --syn $STATE NEW -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,ACK FIN -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags PSH,ACK PSH -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags ACK,URG URG -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK,URG -j DROP
ipt -t mangle -A deny -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
##############################################################
### Цепочки и правила учета трафика - (таблица mangle) ###
##############################################################
# Создаем цепочки учета трафика и добавляем туда правила, с которых снимается статистика
# (поик по ключ. словам "deny", "ACCEPT" и "RETURN").
ipt -t mangle -N _exti # Цепочка учета внешнего входящего трафика.
ipt -t mangle -N _extiall # Цепочка учета внешнего входящего всего трафика.
ipt -t mangle -N _extiweb # Цепочка учета внешнего входящего WEB-трафика.
ipt -t mangle -N _extiftp # Цепочка учета внешнего входящего FTP-трафика.
ipt -t mangle -N _extieml # Цепочка учета внешнего входящего EML-трафика.
ipt -t mangle -N _extixxx # Цепочка учета внешнего входящего прочего трафика.
ipt -t mangle -A _exti -j _extiall
ipt -t mangle -A _exti -p tcp -m multiport --dports 80,443 -j _extiweb
ipt -t mangle -A _exti -p tcp -m multiport --sports 80,443 -j _extiweb
ipt -t mangle -A _exti -p tcp --dport 20:21 -j _extiftp
ipt -t mangle -A _exti -p tcp --sport 20:21 -j _extiftp
ipt -t mangle -A _exti -p tcp -m multiport --dports 25,110,143,587,995 -j _extieml
ipt -t mangle -A _exti -p tcp -m multiport --sports 25,110,143,587,995 -j _extieml
ipt -t mangle -A _exti -j _extixxx
ipt -t mangle -A _extiall -j RETURN # Это правило используется для подсчета трафика.
ipt -t mangle -A _extiweb -j deny # Это правило используется для подсчета трафика.
ipt -t mangle -A _extiftp -j deny # Это правило используется для подсчета трафика.
ipt -t mangle -A _extieml -j deny # Это правило используется для подсчета трафика.
ipt -t mangle -A _extixxx -j deny # Это правило используется для подсчета трафика.
ipt -t mangle -N _exto # Цепочка учета внешнего исходящего трафика.
ipt -t mangle -N _extoall # Цепочка учета внешнего исходящего всего трафика.
ipt -t mangle -N _extoweb # Цепочка учета внешнего исходящего WEB-трафика.
ipt -t mangle -N _extoftp # Цепочка учета внешнего исходящего FTP-трафика.
ipt -t mangle -N _extoeml # Цепочка учета внешнего исходящего EML-трафика.
ipt -t mangle -N _extoxxx # Цепочка учета внешнего исходящего прочего трафика.
ipt -t mangle -A _exto -j _extoall
ipt -t mangle -A _exto -p tcp -m multiport --dports 80,443 -j _extoweb
ipt -t mangle -A _exto -p tcp -m multiport --sports 80,443 -j _extoweb
ipt -t mangle -A _exto -p tcp --dport 20:21 -j _extoftp
ipt -t mangle -A _exto -p tcp --sport 20:21 -j _extoftp
ipt -t mangle -A _exto -p tcp -m multiport --dports 25,110,143 -j _extoeml
ipt -t mangle -A _exto -p tcp -m multiport --sports 25,110,143 -j _extoeml
ipt -t mangle -A _exto -j _extoxxx
ipt -t mangle -A _extoall -j RETURN # Это правило используется для подсчета трафика.
ipt -t mangle -A _extoweb -j ACCEPT # Это правило используется для подсчета трафика.
ipt -t mangle -A _extoftp -j ACCEPT # Это правило используется для подсчета трафика.
ipt -t mangle -A _extoeml -j ACCEPT # Это правило используется для подсчета трафика.
ipt -t mangle -A _extoxxx -j ACCEPT # Это правило используется для подсчета трафика.
ipt -t mangle -N _inti # Цепочка фильтрации входящего локального трафика.
for lan in $LANS; do
ipt -t mangle -A _inti -d $lan -j ACCEPT # Внутренний входящий трафик к серверу.
done
ipt -t mangle -A _inti -j deny # Переходим в цепочку запрета.
ipt -t mangle -N _into # Цепочка учета внешнего входящего трафика по хостам и сетям.
# Отлавливаем внешний
ipt -t mangle -A PREROUTING -i $IF_EXT -j _exti # входящий трафик.
ipt -t mangle -A POSTROUTING -o $IF_EXT -j _exto # исходящий трафик.
# Отлавливаем внутренний
ipt -t mangle -A PREROUTING -i $IFs_INT -j _inti # входящий трафик.
ipt -t mangle -A POSTROUTING -o $IFs_INT -s $IP_EXT -j ACCEPT # исходящий в LAN, с внешнего интерфейса - его не считаем.
[ "$WEBPROXY" ] && \
for lan in $LANS; do
ipt -t mangle -A POSTROUTING -o $IFs_INT -p tcp --sport $WEBPORT -s $lan -j _into # проксируемый LAN->LAN, WEB.
ipt -t mangle -A POSTROUTING -o $IFs_INT -s $lan -j ACCEPT # остальной LAN->LAN - его не считаем.
done
ipt -t mangle -A POSTROUTING -o $IFs_INT -j _into # остальной ->LAN - внешний непроксируемый (HTTPS,FTP,EML,ICQ,...).
# # Отлавливаем маркированный исходящий трафик с внутреннего интерфейса.
# ipt -t mangle -A POSTROUTING -o $IFs_INT -m tos --tos 0x02 -o $IFs_INT -j _into
# ipt -t mangle -A FORWARD -i $IFs_INT -s 10.5.33.212 -j TOS --set-tos 0x10
enable_gw # Включаем маршрутизацию/NAT через внутренний шлюз к сетям.
# Разрешаем почтовые сервисы.
[ "$EMLSERVICES" ] && \
for emlservice in $EMLSERVICES; do
allow_tcpservice "$emlservice" '25,110' $LIMIT_EML
done
# Разрешаем web-сервисы.
[ "$WEBSERVICES" ] && \
for webservice in $WEBSERVICES; do
allow_tcpservice "$webservice" '80,443' $LIMIT_WEB
done
###################################################
### DNAT - Цепочка PREROUTING (таблица nat) ###
###################################################
# # DNAT из локальной сети для FTP.
# ipt -t nat -A PREROUTING -p tcp -i $IFs_INT -d 192.168.0.5 --dport 20:21 -j DNAT --to-destination 192.168.34.211
# # DNAT из Интернет для RDP.
# ipt -t nat -A PREROUTING -p tcp -d $IP_EXT --dport 3389 -j DNAT --to-destination 192.168.1.103:3389
# ipt -t nat -A PREROUTING -p tcp -d 57.67.17.135 -j DNAT --to-destination 192.168.100.1
# ipt -t nat -A PREROUTING -p tcp -d 63.87.6.92 -j DNAT --to-destination 192.168.100.1
# DNAT для Exchange (RPC Over HTTPs)
[ "$HOSTNAME" == 'main' ] && dnat '10.124.8.133' '443' '443'
#######################################################
### REDIRECT - Цепочка PREROUTING (таблица nat) ###
#######################################################
# Закрываем порты, на которые делаем перенаправление.
if [ "$FTPPROXY" == 'FROX' ]; then
ipt -t nat -A PREROUTING -p tcp -i $IF_EXT --dport 2121 -j DROP
for ip_int in $IPs_INT; do ipt -t nat -A PREROUTING -p tcp -d $ip_int --dport 2121 -j DROP; done
fi
if [ "$WEBPROXY" == 'SQUID' ]; then
ipt -t nat -A PREROUTING -p tcp -i $IF_EXT --dport 3128 -j DROP
for ip_int in $IPs_INT; do ipt -t nat -A PREROUTING -p tcp -d $ip_int --dport 3128 -j DROP; done
fi
if [ "$WEBPROXY" == 'DGSQUID' ]; then
ipt -t nat -A PREROUTING -p tcp -i $IF_EXT -d $IP_EXT -m multiport --dports 3128,8080 -j DROP
for ip_int in $IPs_INT; do ipt -t nat -A PREROUTING -p tcp -d $ip_int -m multiport --dports 3128,8080 -j DROP; done
fi
# Избавляемся от LAN->LAN/REMOTE_LAN-трафика в этой цепочке.
for lan in $LANS $REMOTE_LANS; do ipt -t nat -A PREROUTING -i $IFs_INT -d $lan -j RETURN; done
# Перенаправляем LAN->EXT-трафик.
[ "$FTPPROXY" == 'FROX' ] && ipt -t nat -A PREROUTING -i $IFs_INT -p tcp --dport 21 -j REDIRECT --to-ports 2121
[ "$WEBPROXY" == 'SQUID' ] && ipt -t nat -A PREROUTING -i $IFs_INT -p tcp --dport 80 -j REDIRECT --to-ports 3128
[ "$WEBPROXY" == 'SQUID' ] && ipt -t nat -A PREROUTING -i $IFs_INT -p tcp --dport 8080 -j REDIRECT --to-ports 3128
[ "$WEBPROXY" == 'DGSQUID' ] && ipt -t nat -A PREROUTING -i $IFs_INT -p tcp --dport 80 -j REDIRECT --to-ports 8080
################################### Правила, в которые попадает больше всего трафика,
### Цепочки (таблица filter) ### ставим повыше для увеличения скорости и снижения нагрузки на CPU).
###################################
# ipt -t filter -A INPUT -m mac --mac-source 00:18:f3:a3:3f:24 -j DROP # Блокируем входящий трафик с MAC-адреса (ogk812).
# ipt -t filter -A FORWARD -p udp -m length --length 39 -m u32 --u32 '27&0x8f=7' --u32 '31=0x527c4833' -j DROP # Режем Skype.
ipt -t filter -A INPUT $STATE ESTABLISHED,RELATED -j ACCEPT # Установленные соединения к серверу.
ipt -t filter -A FORWARD -o $IFs_INT $STATE ESTABLISHED,RELATED -j ACCEPT # Исходящие установленные соединения с внутренних интерфейсов.
ipt -t filter -A OUTPUT -o $IF_EXT -s $IP_EXT -j ACCEPT # Исходящий с внешнего интерфейса наружу.
for lan in $LANS; do
ipt -t filter -A FORWARD -i $IFs_INT -d $lan -j ACCEPT # Транзитный из локальных сетей в локальные сети.
ipt -t filter -A OUTPUT -o $IFs_INT -p tcp -s $lan --sport ! $WEBPORT -j ACCEPT # Исходящий TCP, кроме WEB, с внутреннего интерфейса вовнутрь.
ipt -t filter -A OUTPUT -o $IFs_INT -p udp -s $lan -j ACCEPT # Исходящий UDP с внутренних интерфейсов вовнутрь.
[ "$REMOTE_LANS" ] && \
for remote_lan in $REMOTE_LANS; do
ipt -t filter -A INPUT -s $remote_lan -d $lan -j ACCEPT # Входящий из удалённых локальных сетей в локальные сети.
ipt -t filter -A FORWARD -s $remote_lan -d $lan -j ACCEPT # Транзитный из удалённых локальных сетей в локальные сети.
ipt -t filter -A FORWARD -s $lan -d $remote_lan -j ACCEPT # Транзитный из локальных сетей в удалённые локальные сети.
ipt -t filter -A OUTPUT -s $lan -d $remote_lan -j ACCEPT # Исходящий из локальных сетей в удалённые локальные сети.
ipt -t nat -A POSTROUTING -s $lan -d $remote_lan -j ACCEPT # Не допускаем SNAT из локальных сетей в удалённые локальные сети.
done
done
# ICMP (type: 0-ответ "Echo reply", 8-запрос "Echo request", 11-ответ "TTL equals 0").
ipt -t filter -A INPUT -p icmp -j ACCEPT # Входящий ICMP.
# ipt -t filter -A INPUT -p icmp --icmp-type 0 -j ACCEPT # Входящий ICMP.
# ipt -t filter -A INPUT -p icmp --icmp-type 8 -j ACCEPT # Входящий ICMP.
# ipt -t filter -A INPUT -p icmp --icmp-type 11 -j ACCEPT # Входящий ICMP.
ipt -t filter -A OUTPUT -p icmp -j ACCEPT # Исходящий ICMP.
ipt -t filter -A FORWARD -p icmp -j ACCEPT # ICMP.
[ "$SNAT" ] && \
for lan in $LANS; do
ipt -t nat -A POSTROUTING -p icmp -s $lan -o $IF_EXT -j SNAT --to-source $IP_EXT # NAT для ICMP.
done
[ "$FTPPROXY" ] && \
for lan in $LANS; do
ipt -t filter -A INPUT -p tcp -i $IFs_INT -d $lan --dport 2121 -j ACCEPT # Входящий локальный Frox.
done
printf '\n[ deny rules processing ]\n' ; ENABLE_D='Y'; ENABLE_IEC='' ; ENABLE_A='' ; . $CONFIGFILE # Подключаем $CONFIGFILE 2 раз - выполняем d().
printf '\n[ policy rules processing ]\n'; ENABLE_D='' ; ENABLE_IEC='Y'; ENABLE_A='' ; . $CONFIGFILE # Подключаем $CONFIGFILE 3 раз - выполняем i(),e(),c().
printf '\n[ allow rules processing ]\n' ; ENABLE_D='' ; ENABLE_IEC='' ; ENABLE_A='Y'; . $CONFIGFILE # Подключаем $CONFIGFILE 4 раз - выполняем a(),A().
ipt -t filter -A FORWARD -i $IF_EXT -p tcp --sport 1024: --dport 1024: -j DROP # Запрещаем соединения с
ipt -t filter -A FORWARD -o $IF_EXT -p tcp --sport 1024: --dport 1024: -j DROP # непривелигированных портов
ipt -t filter -A FORWARD -i $IF_EXT -p udp --sport 1024: --dport 1024: -j DROP # на непривелигированные
ipt -t filter -A FORWARD -o $IF_EXT -p udp --sport 1024: --dport 1024: -j DROP # на внешнем интерфейсе.
# Чтобы оставшийся трафик не вернулся в родительские цепочки подсчета, разрешаем его.
ipt -t mangle -A deny -j ACCEPT
ipt_end # Применяем команды iptables, если необходимо.
dg_end # Перезапускаем DansGuardian, если необходимо.
[ -a "$DNSROOTDIR/etc/named.conf" ] && $NICE service named reload # Перечитываем DNS-зоны.
lock_unset # Удаляем блокировку запуска.
status # Показываем статус.
}
fwsave() # fwsave () - Сохраняет правила.
{
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
iptables-save>"$IPTABLESFILE"
lock_unset # Удаляем блокировку запуска.
}
fwview() # (OPTIONS,SUBSTR) - Просм. цепочки [совп. с п/строкой]
{
printf '\n************\nMANGLE table\n************\n\n' >"/tmp/fwtraf.fwview.$$"; iptables -t mangle -L $1>>"/tmp/fwtraf.fwview.$$"
printf '\n************\nFILTER table\n************\n\n'>>"/tmp/fwtraf.fwview.$$"; iptables -t filter -L $1>>"/tmp/fwtraf.fwview.$$"
printf '\n************\nNAT table \n************\n\n'>>"/tmp/fwtraf.fwview.$$"; iptables -t nat -L $1>>"/tmp/fwtraf.fwview.$$"
if [ "$2" ]; then
cat 2>/dev/null "/tmp/fwtraf.fwview.$$"|grep -ai "$2">"/tmp/fwtraf.fwview1.$$"
move_file "/tmp/fwtraf.fwview1.$$" "/tmp/fwtraf.fwview.$$"
fi
mc -e "/tmp/fwtraf.fwview.$$"
rm -f "/tmp/fwtraf.fwview.$$"
}
fwviewb() { mc -v "$IPTABLESFILE"; } # Просм. правила, уст. при загрузке.
fwviewi() { mc -v "$IPTFILE"; } # Просм. тек. команды iptables.
fwviewio(){ mc -v "$IPTFILE.old"; } # Просм. предыд. команды iptables.
fwconf() { mc -e "${CONFIGFILE//.tmp}"; } # Редакт. конфиг. файл.
dginet() # (MODE) - Меняет последнюю группу фильтрации на первую (т.е. включает Интернет) или наооборот.
{
[ "$DG_CONF" ] || { printf 'ERROR: variable "DG_CONF" not found\a\n' ; exit 1; }
[ -a "$DG_CONF" ] || { printf "ERROR: file \"$DG_CONF\" not found\a\n" ; exit 1; }
[ "$DG_FGRP" ] || { printf 'ERROR: parameter "filtergroups" not found\a\n' ; exit 1; }
[ "$DG_FGRPLIST" ] || { printf 'ERROR: parameter "filtergroupslist" not found\a\n'; exit 1; }
[ -a "$DG_FGRPLIST" ] || { printf "ERROR: file \"$DG_FGRPLIST\" not found\a\n" ; exit 1; }
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
case "$1" in
on ) cat 2>/dev/null "$DG_FGRPLIST"|sed 2>/dev/null -e "s/=filter${DG_FGRP}/= filter1/g">"/tmp/filtergroupslist.$$" ;;
off) cat 2>/dev/null "$DG_FGRPLIST"|sed 2>/dev/null -e "s/= filter1/=filter${DG_FGRP}/g">"/tmp/filtergroupslist.$$" ;;
esac
[ -a "/tmp/filtergroupslist.$$" ] || { printf "ERROR: file \"/tmp/filtergroupslist.$$\" not found\a\n"; exit 1; }
diff &>/dev/null "/tmp/filtergroupslist.$$" "$DG_FGRPLIST" || \
{
cat 2>/dev/null "/tmp/filtergroupslist.$$">"$DG_FGRPLIST"
service dansguardian restart
}
rm -f "/tmp/filtergroupslist.$$"
lock_unset # Удаляем блокировку запуска.
}
trafhourly() # () - Выполняется в 58 минут каждого часа.
{
local dt=`date +%Y%m%d%H%M`
mkdir -p "$IPDBDIR/EXT_IN" "$IPDBDIR/EXT_IN_WEB" "$IPDBDIR/EXT_IN_FTP" "$IPDBDIR/EXT_IN_EML" "$IPDBDIR/EXT_IN_XXX"
mkdir -p "$IPDBDIR/EXT_OUT" "$IPDBDIR/EXT_OUT_WEB" "$IPDBDIR/EXT_OUT_FTP" "$IPDBDIR/EXT_OUT_EML" "$IPDBDIR/EXT_OUT_XXX"
iptables 2>/dev/null -t mangle -L _extiall -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="RETURN") {print date,$2>>outdir"/EXT_IN/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extiweb -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="deny") {print date,$2>>outdir"/EXT_IN_WEB/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extiftp -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="deny") {print date,$2>>outdir"/EXT_IN_FTP/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extieml -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="deny") {print date,$2>>outdir"/EXT_IN_EML/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extixxx -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="deny") {print date,$2>>outdir"/EXT_IN_XXX/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extoall -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="RETURN") {print date,$2>>outdir"/EXT_OUT/fwtraf_counter" }}'
iptables 2>/dev/null -t mangle -L _extoweb -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="ACCEPT") {print date,$2>>outdir"/EXT_OUT_WEB/fwtraf_counter"}}'
iptables 2>/dev/null -t mangle -L _extoftp -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="ACCEPT") {print date,$2>>outdir"/EXT_OUT_FTP/fwtraf_counter"}}'
iptables 2>/dev/null -t mangle -L _extoeml -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="ACCEPT") {print date,$2>>outdir"/EXT_OUT_EML/fwtraf_counter"}}'
iptables 2>/dev/null -t mangle -L _extoxxx -v -x -n -Z|awk -v outdir=$IPDBDIR -v date=$dt '{if ($3=="ACCEPT") {print date,$2>>outdir"/EXT_OUT_XXX/fwtraf_counter"}}'
iptables 2>/dev/null -t mangle -L _into -v -x -n -Z \
|while read pkts bytes target prot opt in out src dst; do
if [ "$target" == 'ACCEPT' -a "$bytes" != '0' ]; then
mkdir -p "$IPDBDIR/${dst/\/*}"
echo>>"$IPDBDIR/${dst/\/*}/fwtraf_counter" "$dt $bytes"
fi
done
find 2>/dev/null $IPDBDIR/*/fwtraf_counter -type f -mtime +90 -exec rm -rf {} \; # Удаляем файлы, не обновлявшиеся в течение 90 суток.
}
trafmake_body() # (FILEMASK,FILEMASK_DESC) - Дописывает тело отчета по указанной маске.
{
cat>>"$REPORTFILE"<<*
*
:>"/tmp/fwtraf.trafmake_body.$$"
local yyyymmdd=`date +%Y%m%d`
local yyyymm=`date +%Y%m`
local yyyy=`date +%Y`
cd "$IPDBDIR"
for ip in $1; do
[ -a "$ip/fwtraf_counter" ] || continue
local tr_d=`summa "$yyyymmdd" "$ip/fwtraf_counter"`
local tr_m=`summa "$yyyymm" "$ip/fwtraf_counter"`
local tr_y=`summa "$yyyy" "$ip/fwtraf_counter"`
local name=`tail 2>/dev/null -n1 "$ip/fwtraf_name" |sed -e "s/${N}${BLANK1}//"`
local access=`tail 2>/dev/null -n1 "$ip/fwtraf_access"|sed -e "s/${N}${BLANK1}//"`
local desc=`tail 2>/dev/null -n1 "$ip/fwtraf_desc" |sed -e "s/${N}${BLANK1}//"`
local cmd=`echo "$access"|awk '{print $1}'`
local ports=`echo "$access"|awk '{print $2}'`
local wa=`echo "$access"|awk '{print $3}'`
local limit=`echo "$access"|awk '{print $4}'`
local title=' '; [[ "$access" > ' ' ]] && \
{
case "$cmd" in
a) title="${ports//all/Все}" ;;
d) title="Закрыты: ${ports//all/все}" ;;
esac
case "$ports" in
*web*|all|!*) case "$wa" in
0) title="$title. Web-доступ: полный" ;;
*) title="$title. Web-доступ: $wa группа" ;;
esac
;;
esac
[[ "$limit" == [0-9]* ]] && title="$title. Скорость: $limit пакет./сек."
}
echo>>"/tmp/fwtraf.trafmake_body.$$" "$tr_d $tr_m $tr_y $ip %$name %${title// /%} %${desc// /%}"
done
# Одеваем тело в HTML.
sort -rnk3<"/tmp/fwtraf.trafmake_body.$$" \
|awk '{if ($3>"")
{
CONVFMT="%0.f";
printf "\n" , c=c?"":" bgcolor=#E0E0E0", $6;
printf "
\n";
}
}' \
|sed -e 's/\/весь/g;
s/\/весь/g;
s/\/- web/g;
s/\/- web/g;
s/\/- ftp/g;
s/\/- ftp/g;
s/\/- email/g;
s/\/- email/g;
s/\/- прочий/g;
s/\/- прочий/g;
s/%/ /g;' \
>>"$REPORTFILE"
echo>>"$REPORTFILE" '
|
| $2 трафик (Мб) с начала:
| суток
| месяца
| года
|
| Комментарии
|
|
|
|
|
|
|
|
|
|
|
%s\n" , n+=1;
printf " | \n";
if ($5>"%") printf " | %s\n", $4, $4;
else printf " | %s\n" , $4;
printf " | \n";
printf " | %s\n" , $5;
printf " | %s\n" , $1/1048576;
printf " | %s\n" , $2/1048576;
printf " | %s\n" , $3/1048576;
printf " | \n";
printf " | %s\n" , $7;
printf " |
'
echo>>"$REPORTFILE" '
'
rm -f "/tmp/fwtraf.trafmake_body.$$"
}
trafmake() # () - Создает отчет о трафике с начала суток/месяца/года по текущее время в $REPORTFILE.
{
echo >"$REPORTFILE" ''
echo>>"$REPORTFILE" ''
echo>>"$REPORTFILE" "$(env LC_ALL=ru_RU.KOI-8R date +'%e %b %Y. %A, %T')"
trafmake_body 'EXT_IN*' 'Суммарный входящий'
trafmake_body 'EXT_OUT*' 'Суммарный исходящий'
trafmake_body '*.*' 'Входящий'
echo>>"$REPORTFILE" ''
# Создаем индексный файл.
cd "$REPORTDIR"
printf>'index.htm' 'FwTraf\n'
for file in ????-??-??.htm; do
[[ ${file//*-/} == '01.htm' ]] && printf>>'index.htm' '
\n'
printf>>'index.htm' "${file//.htm/}\n"
done
printf>>'index.htm' '\n'
}
trafsend() # (REPEML) - Отправляет отчет о трафике на адрес $REPEML.
{
[ "$1" ] && sendmail $1<<*
From: <$HOSTNAME>
To: <$1>
Subject: FWTraf Report
MIME-Version: 1.0
Content-Type: text/html;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
`cat 2>/dev/null "$REPORTFILE"`
*
}
status() # () - Показывает статус.
{
local all_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\' "$CONFIGFILE"|wc -l`
local _users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!' "$CONFIGFILE"|wc -l`
local web_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(web|http|https|80|443)\>' "$CONFIGFILE"|wc -l`
local _web_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(web|http|https|80|443)\>' "$CONFIGFILE"|wc -l`
local ftp_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(ftp|21)\>' "$CONFIGFILE"|wc -l`
local _ftp_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(ftp|21)\>' "$CONFIGFILE"|wc -l`
local smtp_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(smtp|25)\>' "$CONFIGFILE"|wc -l`
local _smtp_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(smtp|25)\>' "$CONFIGFILE"|wc -l`
local pop3_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(pop3|110)\>' "$CONFIGFILE"|wc -l`
local _pop3_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(pop3|110)\>' "$CONFIGFILE"|wc -l`
local imap_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(imap|143)\>' "$CONFIGFILE"|wc -l`
local _imap_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(imap|143)\>' "$CONFIGFILE"|wc -l`
local icq_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*[^\!]\<(icq|5190)\>' "$CONFIGFILE"|wc -l`
local _icq_users=`egrep '^[ \t]*a[ \t]+[0-9\.]+[ \t]+[A-Za-z0-9_-]+[ \t]+.*\!\<(icq|5190)\>' "$CONFIGFILE"|wc -l`
local dns_records1=`egrep '^[ \t]*[ad][ \t]+10\.*' "$CONFIGFILE"|wc -l`
local dns_records2=`egrep '^[ \t]*[ad][ \t]+172\.16\.*' "$CONFIGFILE"|wc -l`
local dns_records3=`egrep '^[ \t]*[ad][ \t]+192\.168\.*' "$CONFIGFILE"|wc -l`
local ipdbdir_size=`du -s -l -m ${IPDBDIR%%/}|awk '{print $1}'`
echo
echo " Внешний интерфейс: $IF_EXT"
echo "Пользователей с полным доступом: $all_users"
echo " WEB-пользователей: $((web_users + all_users + _users - _web_users ))"
echo " FTP-пользователей: $((ftp_users + all_users + _users - _ftp_users ))"
echo " SMTP-пользователей: $((smtp_users + all_users + _users - _smtp_users))"
echo " POP3-пользователей: $((pop3_users + all_users + _users - _pop3_users))"
echo " IMAP-пользователей: $((imap_users + all_users + _users - _imap_users))"
echo " ICQ-пользователей: $((icq_users + all_users + _users - _icq_users ))"
echo " Записей в DNS: $((dns_records1 + dns_records2 + dns_records3 ))"
echo " Размер базы: $ipdbdir_size Мб"
echo
local warning=`cat 2>/dev/null '/var/log/messages'|grep -a 'ip_conntrack: table full'|tail -n1`
if [ "$warning" ]; then
printf "WARNING: $warning\a\n\n"
printf 'Run the command "fwtraf topconntrack" to view details.\n\n'
fi
}
topconnects() # () - Показывает IP, превышающие лимиты подключений к серверу на порт.
{
cat 2>/dev/null "$MESSAGES" \
|grep -a 'fwtraf_' \
|awk '{print $9,$18,$19}' \
|sed -e 's/SRC=//;s/SPT=[0-9]\+//;s/DPT=//;s/WINDOW=[0-9]\+//' \
|sort -gr \
|uniq -c \
|sort -gr \
|head -n20 \
|while read top ip port; do
local desc=`tail 2>/dev/null -n1 "$IPDBDIR/$ip/fwtraf_desc"|sed -e "s/${N}${BLANK1}//"`
if [ -z "$desc" ]; then
desc=`dig +short -x $ip|head -n1`
desc=${desc//;;*/}
desc=${desc%.}
fi
printf '%-7s %-7s %-15s #%s\n' "$top" "[$port]" "$ip" " $desc"
done
echo
}
toptraffic() # () - Показывает счётчики трафика файервола.
{
iptables -t mangle -L _into -v -x -n \
|while read pkts bytes target prot opt in out src dst; do
[ "$target" == "ACCEPT" -a "$bytes" != '0' ] && echo "$bytes ${dst/\/*}"
done \
|sort -gr \
|head -n20 \
|while read bytes ip; do
local desc=`tail 2>/dev/null -n1 "$IPDBDIR/$ip/fwtraf_desc"|sed -e "s/${N}${BLANK1}//"`
printf '%-8s %-15s %s\n' "$((bytes/1048576))" "$ip" "$desc"
done
}
topconntrack()
{
# Состояние Время ожидания
# ----------- --------------
# NONE 30 минут
# ESTABLISHED 5 дней
# SYN_SENT 2 минуты
# SYN_RECV 60 секунд
# FIN_WAIT 2 минуты
# TIME_WAIT 2 минуты
# CLOSE 10 секунд
# CLOSE_WAIT 12 часов
# LAST_ACK 30 секунд
# LISTEN 2 минуты
local tmpfile="/tmp/fwtraf_topconntrack.$$"
echo
echo "Maximal connections count: `cat 2>/dev/null /proc/sys/net/ipv4/ip_conntrack_max`"
echo "Current connections count: `cat 2>/dev/null /proc/net/ip_conntrack|wc -l`"
echo
cat 2>/dev/null '/proc/net/ip_conntrack'>"$tmpfile"
echo 'Top protocols:'
echo
cat 2>/dev/null "$tmpfile" \
|awk '{print $1}' \
|sort \
|uniq -c \
|sort -gr
echo
echo 'Top state:'
echo
cat 2>/dev/null "$tmpfile" \
|egrep -a ' (NONE|ESTABLISHED|SYN_SENT|SYN_RECV|FIN_WAIT|TIME_WAIT|CLOSE|CLOSE_WAIT|LAST_ACK|LISTEN) ' \
|awk '{print $4}' \
|sort \
|uniq -c \
|sort -gr
echo
echo 'Top source IP (tcp):'
echo
cat 2>/dev/null "$tmpfile" \
|grep -a 'tcp' \
|awk '{print $5}' \
|sort \
|uniq -c \
|sort -gr \
|head -n 20 \
|sed -e 's/src=//g'
echo
echo 'Top destination IP (tcp):'
echo
cat 2>/dev/null "$tmpfile" \
|grep -a 'tcp' \
|awk '{print $6}' \
|sort \
|uniq -c \
|sort -gr \
|head -n 20 \
|sed -e 's/dst=//g'
echo
echo 'Top detination port (tcp):'
echo
cat 2>/dev/null "$tmpfile" \
|grep -a 'tcp' \
|awk '{print $8}' \
|sort \
|uniq -c \
|sort -gr \
|head -n 20 \
|sed -e 's/dport=//g'
echo
rm -f "$tmpfile"
}
backup() # () - Сохраняет скрипт, конфигурацию, логи и отчеты в архив.
{
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
mkdir -p '/backup'
tar czf "/backup/fwtraf_${HOSTNAME}_$(date +%Y%m%d).tgz" "$0" "$CONFIGDIR" "$IPDBDIR" "$REPORTDIR" '/etc/cron.d/fwtraf' /bin/phoss* /bin/nbtscan*
lock_unset # Удаляем блокировку запуска.
}
restore() # () - Восстанавливает все из архива.
{
[ -a "$1" ] || { printf 'ERROR: backup file not found\a\n'; exit 1; }
lock_check # Проверяем, не запущен ли скрипт уже.
lock_run # Устанавливаем блокировку запуска.
tar xzf "$1" -C /
lock_unset # Удаляем блокировку запуска.
}
ipdbfind() # (SUBSTR,[IP_FIELD]) - Ищет все строки, совп. с заданной подстрокой в БД.
{
[[ "$@" < '!' ]] && { printf 'ERROR: substring not specified\a\n'; exit 1; }
cat 2>/dev/null "$CONFIGFILE"|grep -ai "$1"|sed -e "s/^$BLANK1//g; s/$BLANK1/ /g"
echo
cat 2>/dev/null "$DHCPD_CONF"|grep -ai "$1"|sed -e "s/^$BLANK1//g; s/$BLANK1/ /g"
echo
grep 2>/dev/null -air "$1" "$IPDBDIR$2" \
|sort -k1 -r \
|sed -e 's/^\/var\/log\/ipdb\/\(.*\)\/\(.*\):\([0-9]\{4\}\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\) \(.*\)/\3-\4-\5 \6:\7 \1 \2 \8/'
echo
}
ipdbdel() # (SUBSTR) - Удаляет все строки, совп. с заданной подстрокой из БД.
{
[[ "$@" < '!' ]] && { printf 'ERROR: substring not specified\a\n'; exit 1; }
grep -air "$@" "$IPDBDIR" \
|cut -d':' -f1 \
|sort \
|uniq \
|while read file other; do
cat 2>/dev/null "$file" \
|grep -aiv "$@" \
>"/tmp/fwtraf.ipdbdel.$$"
move_file "/tmp/fwtraf.ipdbdel.$$" "$file"
done
}
ipdbclear() # () - Очищает ip-базу данных от старых данных (время выполнения ~1,5 мин).
{
local cutdate=`date -d '-12 month' +%Y%m%d0000` # Дата, до которой удаляются данные.
for file in $IPDBDIR/*/{fwtraf,nbtscan,phoss}_*; do
cat 2>/dev/null "$file" \
|egrep -av '^[0-9]+ 0$' \
|awk -v cdate=$cutdate '{if ($1>cdate) printf "%s\n",$0}' \
>"/tmp/fwtraf.ipdbclear.$$"
if [[ "`ls 2>/dev/null -s /tmp/fwtraf.ipdbclear.$$`" == '0 '* ]]; then
rm -f "/tmp/fwtraf.ipdbclear.$$" "$file"
else
move_file "/tmp/fwtraf.ipdbclear.$$" "$file"
fi
done
}
ipmove() # (IP_SRC,IP_DST) - Удаляет каталог IP_DST и переименовывает каталог IP_SRC в IP_DST.
{
[[ "$IPDBDIR" < '/#' ]] && { printf 'ERROR: IPDBDIR not valid\a\n'; exit 1; }
ip_or_net_valid "$1" || { printf 'ERROR: ip_src not valid\a\n'; exit 1; }
ip_or_net_valid "$2" || { printf 'ERROR: ip_dst not valid\a\n'; exit 1; }
if [ -d "$IPDBDIR/$1" ]; then
[ -d "$IPDBDIR/$2" ] && rm -fr "$IPDBDIR/$2"
mkdir -p "$IPDBDIR/$2"
cp 2>/dev/null -fR --reply=yes $IPDBDIR/$1/* $IPDBDIR/$2/
[ -d "$IPDBDIR/$2" ] && rm -fr "$IPDBDIR/$1"
else
printf "ERROR: \"$IPDBDIR/$1\" not exist\a\n"; exit 1
fi
}
help() # () - Выводит помощь.
{
clear
cat<<*
----------------------------------
УПРАВЛЕНИЕ FIREWALL / УЧЕТ ТРАФИКА
----------------------------------
Использование: fwtraf [команда]
Команды:
fwaccept - разрешить все пакеты, отключить SNAT
fwsimple - уст. простые правила для всех локальных сетей
fwsingle ip - уст. простые правила для одного локального IP
fwnormal - уст. правила для нормальной работы
fwsave - сохр. тек. правила
fwconf - редакт. конфиг. файл
fwview ["substr"] - просм. тек. цепочки iptables
fwviewb - просм. правила, уст. при загрузке
fwviewi - просм. тек. команды iptables
fwviewio - просм. предыд. команды iptables
dginet_on - вкл. Интернет пользователям с гр. дост. "$DG_FGRP"
dginet_off - выкл. Интернет пользователям с гр. дост. "$DG_FGRP"
trafmake - создать отчет о трафике
trafsend "email" - отослать отчет о трафике
ipdbfind "substr" [/ip/field] - искать все строки в БД, совп. с п/строкой
ipdbdel "substr" - удалить все строки из БД, совп. с п/строкой
ipdbclear - очистить БД от данных годичной давности
ipmove ip_src ip_dst - переименовать ip_src в ip_dst
backup - сделать резервную копию
restore "backupfile" - восстановить резервную копию
lock - заблокировать выполнение (выполняется авт.)
unlock - разблокировать выполнение (опасно)
status - показать статус
topconnects - показать IP, превышающ. лимиты подкл. к серверу
toptraffic - показать счётчики трафика файервола
topconntrack - показать статистику таблицы отслеживанияй соединений
*
exit 1
}
################################################################################################
# НАЧАЛО ПРОГРАММЫ
################################################################################################
mkdir -p "$CONFIGDIR" "$IPDBDIR" "$REPORTDIR" # Создаем каталоги.
if [ -a "$CONFIGFILE" ]; then # Если существует $CONFIGFILE
rm -f "$CONFIGFILE.tmp"
cp -af "$CONFIGFILE" "$CONFIGFILE.tmp"
CONFIGFILE=$CONFIGFILE.tmp
ENABLE_D=''; ENABLE_IEC=''; ENABLE_A=''; . $CONFIGFILE # Подключаем $CONFIGFILE 1 раз - импортируем переменные.
else
printf "ERROR: configuration file \"$CONFIGFILE\" not found\a\n"; exit 1
fi
# Определяем внешний интерфейс.
if [ "$EXTIF" ]; then
IF_EXT=$EXTIF
else
IF_EXT=`route -n|awk '{if ($1=="0.0.0.0" && $3=="0.0.0.0") print $8}'`
[ "$IF_EXT" ] || \
IF_EXT=`route -n|awk '{if ($2=="0.0.0.0" \
&& $1!~/0\.0\.0\.0/ \
&& $1!~/^10\./ \
&& $1!~/^169\.254\./ \
&& $1!~/^172\.1[6-9]\./ \
&& $1!~/^172\.2[0-9]\./ \
&& $1!~/^172\.31\./ \
&& $1!~/^192\.168\./ \
&& $1 ~/[0-9]+/ ) print $8}'|head -n1`
fi
IF_LO='lo' # Петлевой интерфейс.
IFs_INT="! $IF_EXT" # Внутренние интерфейсы.
IP_LO='127.0.0.1' # IP-адрес петлевого интерфейса.
IP_EXT=`ifconfig|grep -A1 "^${IF_EXT//+/[0-9]\+} "|sed -n 's/inet addr://p'|awk 'END{print $1}'` # IP-адрес внешнего интерфейса (поддержка int+).
# IP_EXT=`ifconfig $IF_EXT|sed -n 's/inet addr://p'|awk '{print $1}'` # IP-адрес внешнего интерфейса.
IPs_INT=`ifconfig|grep -a 'inet addr'|cut -d: -f2|cut -d' ' -f1|grep -av "\<$IP_EXT\>"` # IP-адреса внутренних интерфейсов.
case "$WEBPROXY" in SQUID)WEBPORT=3128;; DGSQUID)WEBPORT=8080;; *)WEBPORT=80;; esac # Определяем WEB-порт.
NICE=`nice 2>/dev/null` # Компенсируем низкий приоритет.
if [[ "$NICE" == -* ]]; then
NICE="nice -n ${NICE/-/+}"
else
NICE=''
fi
case "$1" in
fwaccept ) fwaccept ;;
fwsimple ) fwsimple ;;
fwsingle ) fwsingle "$2" ;;
fwnormal ) fwnormal ;;
fwsave ) fwsave ;;
dginet_on ) dginet 'on' ;;
dginet_off ) dginet 'off' ;;
fwconf ) fwconf ;;
fwview ) fwview '-v -n' "$2" ;;
fwviewb ) fwviewb ;;
fwviewi ) fwviewi ;;
fwviewio ) fwviewio ;;
trafhourly ) trafhourly ;;
trafdaily ) trafdaily ;;
trafmonthly ) trafmonthly ;;
trafyearly ) trafyearly ;;
trafmake ) trafmake ;;
trafsend ) trafsend "$2" ;;
ipdbfind ) ipdbfind "$2" "$3" ;;
ipdbdel ) ipdbdel "$2" ;;
ipdbclear ) ipdbclear ;;
ipmove ) ipmove "$2" "$3" ;;
backup ) backup ;;
restore ) restore "$2" ;;
lock ) lock_check; lock_set ;;
unlock ) lock_unset ;;
status ) status ;;
topconnects ) topconnects ;;
toptraffic ) toptraffic ;;
topconntrack) topconntrack ;;
* ) help ;;
esac
/etc/fwtraf/fwtraf.conf
#!/bin/bash
#----------------------
# Персональные политики
#----------------------
#C IP NAME WA PORTS [LIMIT] DESC
#- --------------- ---------------- -- ------------------------ ---------------------------------------
a 10.0.250.1 pc113 1 !smtp # Компу разрешено всё, кроме SMTP
a 10.1.114.200 nb124 2 web,pop3 10 # Ноутбук, скорость 10 пакетов в секунду
a 10.1.114.201 pc115 3 web # Только WEB
a 10.1.118.200 pc12 3 web,smtp,pop3 # Только WEB и почта
a 10.1.118.201 pc152 2 web,ftp,8888 # Разрешено WEB,FTP, и ещё что-то
a 10.1.124.202 pc128 3 web,ftp,pop3 50 # Разрешено WEB,FTP и получение почты
a 10.1.130.200 pc194 3 web,bc_tc 10 # Финансисты, лимит 10 пакетов/секунду
a 10.1.130.201 pc175 3 web,200,quik,bc_sb # Финансисты. Quick, Банк-клиент "СберБанк"
a 10.3.42.37 pc102 # Ничего не разрешено, кроме PING,TRACEROUTE
d 10.3.46.21 pc417 6 all # Тупой юзер - запрещаем всё
a 10.4.36.101 nb11 1 web,ftp,pop3,rdp 10 # Слишком продвинутый юзер - режем скорость
a 10.5.14.103 pc210 1 all # Начальник отдела - открываем всё что можно
a 10.8.91.202 pc24 2 web,ftp,pop3,oracle # Программер
a 10.16.26.207 pc77 3 web,bc_sb,bc_uc # Банк-клиенты "СберБанк", "ЮникредитБанк"
A 10.127.255.2 mail # Почтовый сервер - оставляем запись в DNS
A 10.127.255.2 mx1 # Почтовый сервер - оставляем запись в DNS
a 10.127.255.128 vpn-user 3 rdp,telnet # VPN-юзер - только RDP и TELNET
#---------------
# Запрещённые IP
#---------------
#C IP NAME WA PORTS DESC
#- --------------- ----------------------------------------------------- -- -------- ---------------------------------------
d 64.233.161.99 google-analytics.com 6 all # Google Spy
d 72.14.209.99 google-analytics.com 6 all # Google Spy
d 72.14.253.99 google-analytics.com 6 all # Google Spy
d 72.14.217.91 sb.l.google.com 6 all # Google Spy
d 72.14.217.93 bu-in-f93.google.com 6 all # Google Spy
d 209.85.137.99 mg-in-f99.google.com 6 all # Google Spy
d 66.249.91.91 kh.l.google.com 6 all # Google
#----------------------------------------------
# Общая политика: разрешённые протоколы и порты
#----------------------------------------------
#C PROT PORTS [LIMIT] [CONN_LIMIT] DESC
#- ---- ---------------------------------- ------- ------------ -------------------------
c udp dns 1000 # DNS
c udp ntp 10 # NTP
c udp traceroute 10 # TRACEROUTE
c tcp fns 1000 # FNS (Федеральная налоговая служба)
c udp bc_sb_udp 1000 # BANKCLIENT СберБанка. VPN
c tcp feanor 100 # FEANOR
c tcp pptp 100 # PPTP
c gre all # GRE for PPTP
c udp 500,4500 1000 # CiscoVPN
e tcp openvpn 1000 10 # OpenVPN
e tcp http,https 1000 # HTTP,HTTPS
i tcp http,https 5000 # HTTP,HTTPS
e tcp smtp,smtpalt 5000 5 # SMTP,SMTPALT
i tcp smtp,smtpalt # SMTP,SMTPALT
e tcp pop3,imap 1000 10 # POP3,IMAP
i tcp pop3,imap 1000 15 # POP3,IMAP
e tcp ftp 1000 10 # FTP
i tcp ftp 5000 10 # FTP
e tcp ssh 20 10 # SSH
i tcp ssh 1000 20 # SSH
e tcp 9090 10 10 # OPENFIRE_CONSOLE
i tcp 9090 10 10 # OPENFIRE_CONSOLE
i tcp webmin,rdp,radmin 1000 20 # WEBMIN,RDP,RADMIN
i udp tftp 100 # TFTP
i tcp smb,rsync 5000 # SMB,RSYNC
i udp smb 5000 # SMB
i udp snmp 20 # SNMP
c tcp jabber 50 # JABBER
#-------------------
# Основные настройки
#-------------------
EXTIF="" # Внешний интерфейс (опр. автоматически, если "")
EXTDOMAINNAME="domain.com" # Внешний домен ("", "domain.com")
LANS="192.168.0.0/24 10.0.0.0/24" # Локальные сети ("xxx.xxx.xxx.xxx/yy")
# REMOTE_LANS="10.128.0.0/16" # Удалённые сети ("xxx.xxx.xxx.xxx/yy")
SNAT="YES" # Трансляция адресов на внешний интерфейс ("","YES")
WEBPROXY="" # WEB-прокси ("","SQUID","DGSQUID")
FTPPROXY="" # FTP-прокси ("","FROX")
REPEML="" # Отчеты по почте ("","root","pupkin@mail.ru")
# GW="192.168.10.254" # Маршрутизация к сетям через шлюз ("","IP")
# SNAT_TO_GW="192.168.10.1" # IP локального интерфейса для SNAT к сетям ("","IP")
# NETS_VIA_GW="194.84.224.0/26 212.176.66.0/24 212.176.70.0/24" # Сети, доступные через шлюз
sbis="83.242.250.67 83.242.250.68" # СБИС++ - электронная отчетность (порт 25)
fstrf="87.226.173.3" # Федеральная служба по тарифам
feanor="195.135.214.6" # Феанор
EMLSERVICES="$sbis $fstrf $feanor" # Сервисы, использующие порты 25,110
dc1="173.194.69.0/24" # Dicter
tc1="46.182.25.0/24 66.102.13.0/24 74.125.0.0/16 74.125.79.96/28" # Translate Client
tc2="74.125.87.96/28 74.125.232.16/29 173.194.32.0/24 174.120.221.88" # Translate Client
tc3="207.46.192.223 209.85.146.0/23 209.85.148.0/23 209.85.173.0/24" # Translate Client
tc4="209.85.175.0/24 209.85.225.0/24 209.85.227.0/24 209.85.229.100/30" # Translate Client
mse1="4.23.0.0/16 64.4.0.0/18 64.209.77.25 65.52.0.0/14 74.125.232.48/30" # Microsoft Security Essentials
mse2="77.67.4.0/24 77.67.29.0/24 80.239.224.0/24 80.239.230.0/24" # Microsoft Security Essentials
mse3="80.239.254.0/24 92.122.208.112 92.123.69.0/24 94.245.64.0/18" # Microsoft Security Essentials
mse4="95.100.131.235 194.221.65.0/26 195.10.0.0/18 207.46.0.0/16" # Microsoft Security Essentials
mse5="213.155.154.0/24 213.199.149.98 217.212.252.128/25" # Microsoft Security Essentials
ds="168.75.151.72" # DraftSight
WEBSERVICES="$dc1 $tc1 $tc2 $tc3 $tc4 $mse1 $mse2 $mse3 $mse4 $mse5 $ds" # Сервисы, использующие порты 80,443
#--------
# СПРАВКА
#--------
# Доступные команды:
# i PROT PORTS [LIMIT [CONN_LIMIT]] - разрешить трафик из внутренних сетей к заданным портам шлюза, уст. лимиты.
# e PROT PORTS [LIMIT [CONN_LIMIT]] - разрешить трафик из внешней сети к заданным портам шлюза, уст. лимиты.
# c PROT PORTS [LIMIT [CONN_LIMIT]] - разрешить трафик из любых сетей к заданным портам шлюза и через него, уст. лимиты.
# [dD] IP NAME [WA [PORTS ]] - прописать в DNS, определить группу WEB-доступа, закрыть tcp/udp-порты.
# [aA] IP NAME [WA [PORTS [LIMIT]]] - прописать в DNS, определить группу WEB-доступа, открыть tcp-порты, уст. лимит.
# Примечание: Большие буквы D,A - прописать в DNS и перезаписать A-запись во внешнем домене IP-адресом из LAN.
#
# Параметры команд:
# PROT: (tcp|udp|gre|icmp) - протокол.
#
# PORTS: p1,..,pN - разрешить порты p1,..,pN (не более 15).
# p1:p2 - разрешить диапазон портов p1-p2.
# [..,]p1-p2[,..] - разрешить порты p1 и p2 и сделать DNAT c EXT_IP:p1 на IP:p2.
# !p1 - разрешить все порты кроме p1.
# all - разрешить все порты и протоколы.
# dns,smtp,pop3,imap,smtpstls,pop3tls,eml, - разрешить порты (не более 15).
# fns,ftp,gpsmon,http,icq,irc,mssql,ntp,
# openvpn,oracle,quik,rdp,radmin,sip,smb,
# snmp,ssh,telnet,torrent,traceroute,web,
# webinar,webmin,webmoney.
#
# LIMIT: N - ограничить скорость N пакетов/сек (2 пак/с=3Кб/с, 5 пак/с=7Кб/с, 10 пак/с=12Кб/с, 30 пак/с=20Кб/с).
# "" - ограничить скорость Squid`ом.
#
# CONN_LIMIT: 0..20 - ограничить кол-во подключений/мин. Лимит действует для каждого IP отдельно.
#
# IP: x.x.x.x[/y] - IP-адрес хоста или сети. Если сеть - группа WEB-доступа не применяется.
#
# NAME: hostname - Имя хоста. Допустимые символы - буквы лат. алфавита, цифры и тире. Точка допускается, но используется
# в качестве разделителя. Имя kms - служебное, для него будет создана SRV-запись, указывающая на KMS.
#
# WA: 0..N - Группа фильтрации (WEB-доступ):
# 0 - разрешено всё (фильрация выключена - IP добавлен в exceptioniplist).
# 1 - разрешено всё.
# 2 - разрешено всё кроме скачивания audio/video.
# 3 - полная фильтрация (для простых пользователей).
# 4 - полная фильтрация + запрещены закачки.
# 5 - запрещено всё кроме domain.com,microsoft.com,windowsupdate.com (для серверов).
# 6 - запрещено всё кроме domain.com.
/etc/cron.d/fwtraf.cron
# Минута Час День месяца Месяц День недели Пользователь Задание
# (0-59) (0-23) (1-31) (1-12) (0-7)
# ------ ------ ----------- ------ ----------- ------------ --------- --------------------------------------------
58 * * * * root /bin/fwtraf trafhourly; /bin/fwtraf trafmake
30 23 * * 0 root /bin/fwtraf ipdbclear
оригинал статьи http://habrahabr.ru/post/146116/