Полезные скрипты наструганные на коленке.

Программирование на sh, быть может немного про альтернативные языки
Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-20 13:37:12

2 lazhu
Зачем Перл?
Это можно сделать на AWK.
Вы же все равно используете AWK ;)
Скорость возрастет в разы.
Если интересно, могу накидать.
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2460 рублей (8 CPU, 8Gb RAM, 2x500Gb HDD, RAID 3ware 9750):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-20 22:33:08

kpp писал(а):2 lazhu
Зачем Перл?
Это можно сделать на AWK.
Вы же все равно используете AWK ;)
Скорость возрастет в разы.
Если интересно, могу накидать.
Да, похоже я изрядно лоханулся.

Код: Выделить всё

values=`awk -v q="'" 'BEGIN {ORS=",";OFS=","}{print "(FROM_UNIXTIME("$8")",q$1q,q$2q,q$3q,q$4q,q$5q,q$6q,q$7q")"}' ${log} | sed 's/,$/;/'`
echo 'INSERT INTO `'${iface}'` (`date`,`src_ip`,`src_port`,`dst_ip`,`dst_port`,`protocol`,`packets`,`bytes`) VALUES' ${values} | ${sql}
отрабатывает моментально :oops:

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 11:52:45

Уже лучше ;)
А как Вам замена:

Код: Выделить всё

awk -v q="'" 'BEGIN {ORS=",";OFS=","}{print "(FROM_UNIXTIME("$8")",q$1q,q$2q,q$3q,q$4q,q$5q,q$6q,q$7q")"}' ${log} | sed 's/,$/;/'
На:

Код: Выделить всё

fmt="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s');"
awk -v fmt=$fmt '{printf fmt, $8,$1,$2,$3,$4,$5,$6,$7}' ${log}
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 11:58:48

И это еще не вся оптимизация - ведь, насколько я понял, цикл while у вас так и остался...
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-21 12:54:44

kpp писал(а):И это еще не вся оптимизация - ведь, насколько я понял, цикл while у вас так и остался...
Нет, цикл убран. AWK выводит весь файл в переменную, которая затем подставляется в sql-запрос.
kpp писал(а):Уже лучше ;)
А как Вам замена:

Код: Выделить всё

awk -v q="'" 'BEGIN {ORS=",";OFS=","}{print "(FROM_UNIXTIME("$8")",q$1q,q$2q,q$3q,q$4q,q$5q,q$6q,q$7q")"}' ${log} | sed 's/,$/;/'
На:

Код: Выделить всё

fmt="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s');"
awk -v fmt=$fmt '{printf fmt, $8,$1,$2,$3,$4,$5,$6,$7}' ${log}
Да, логично, только строки в формуле VALUE должны разделяться запятыми, точка с запятой ставится в конце запроса. Поэтому костыль с седом.

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 13:08:32

lazhu писал(а): ...
Да, логично, только строки в формуле VALUE должны разделяться запятыми, точка с запятой ставится в конце запроса. Поэтому костыль с седом.
Попробуйте мой вариант.
Костыль с седом не нужен, разделители могут быть любые, также как и символы обрамления значений полей.
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-21 13:17:16

kpp писал(а):
lazhu писал(а): ...
Да, логично, только строки в формуле VALUE должны разделяться запятыми, точка с запятой ставится в конце запроса. Поэтому костыль с седом.
Попробуйте мой вариант.
Костыль с седом не нужен, разделители могут быть любые, также как и символы обрамления значений полей.
Тогда придется в awk делать цикл для строк <NR и отдельно последнюю строку. Писанины точно будет больше, а выигрыш в производительности практически нулевой. Хотя и без костылей ;-)

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 13:21:42

Гм.. значит цикл какой-то все таки есть?
Покажите весь скрипт с последними изменениями.
Хотя, как хотите.
В любом случае это обсуждение нужно вести в отдельной теме.
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-21 13:28:34

kpp писал(а):Гм.. значит цикл какой-то все таки есть?
Покажите весь скрипт с последними изменениями.
Цикла нет, просто все строки выводятся с запятой, а сед меняет последнюю на точку с запятой.

Код: Выделить всё

#!/bin/sh

cmd="/usr/local/sbin/ipacctctl"
iface=$1
log="/var/log/ipacct/ng_ipacct.log"
ip=
user=
passwd=
db=
cols='`date`,`src_ip`,`src_port`,`dst_ip`,`dst_port`,`protocol`,`packets`,`bytes`'
sql="/usr/local/bin/mysql --user=${user} --password=${passwd} --database=${db}"

if [ "$2" = "ext"  ]; then
    ${cmd} -i ${iface}_ip_acct:${iface} checkpoint
else
    ${cmd} -o ${iface}_ip_acct:${iface} checkpoint
fi
${cmd} ${iface}_ip_acct:${iface} show >> ${log}
${cmd} ${iface}_ip_acct:${iface} clear

sed -i '' "/${ip}/d" ${log}

values=`awk -v q="'" 'BEGIN {ORS=",";OFS=","}{print "(FROM_UNIXTIME("$8")",q$1q,q$2q,q$3q,q$4q,q$5q,q$6q,q$7q")"}' ${log} | sed 's/,$/;/'`
echo 'INSERT INTO `'${iface}'` ('${cols}') VALUES' ${values} | ${sql}

rm ${log}
Согласен, что с printf код выглядит аккуратнее, но проблема последней запятой все равно остается.

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 13:51:25

Тогда так:

Код: Выделить всё

fmt="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s')"
awk -v fmt=$fmt '{if(s!="")print s","; s=sprintf(fmt,$8,$1,$2,$3,$4,$5,$6,$7)} END{print s";"}' ${log}
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 14:13:24

А если сделать так:

Код: Выделить всё

fmt="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s')"
awk -v fmt=$fmt -v ip="$ip" '$0 !~ ip{if(s!=""){print s","; s="";}; s=sprintf(fmt,$8,$1,$2,$3,$4,$5,$6,$7)} END{if(s!="")print s";"}' ${log}
то избавляемся еще от

Код: Выделить всё

sed -i '' "/${ip}/d" ${log}
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-21 14:16:33

kpp писал(а):Тогда так:

Код: Выделить всё

fmt="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s')"
awk -v fmt=$fmt '{if(s!="")print s","; s=sprintf(fmt,$8,$1,$2,$3,$4,$5,$6,$7)} END{print s";"}' ${log}
:smile: сделал так:

Код: Выделить всё

awk -v fmt=${fmt} 'NR>1{printf ","}{printf fmt, $8,$1,$2,$3,$4,$5,$6,$7} END{print ";"}' ${log}
Да, надо было сесть и спокойно подумать, но в первом часу ночи думалось не очень =)

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 14:28:31

В идеале на выходе awk должен быть полностью весь текст запроса INSERT.
ИМХО.
Все, закругляюсь, что-то меня сегодня занесло :pardon:
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

lazhu
сержант
Сообщения: 176
Зарегистрирован: 2013-08-10 14:28:38
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение lazhu » 2013-11-21 15:46:45

kpp писал(а):В идеале на выходе awk должен быть полностью весь текст запроса INSERT.
ИМХО.
Все, закругляюсь, что-то меня сегодня занесло :pardon:
Мда, Вы все-таки заставили меня засесть за это покапитальнее ;-)
Окончательно этот кусок выглядит так:

Код: Выделить всё

ip="192.168.0.1"
start="INSERT INTO \`${iface}\` (\`date\`,\`src_ip\`,\`src_port\`,\`dst_ip\`,\`dst_port\`,\`protocol\`,\`packets\`,\`bytes\`) VALUES "
end="(FROM_UNIXTIME(%s),'%s','%s','%s','%s','%s','%s','%s')"
awk -v ip=${ip} -v start="${start}" -v end=${end} '$0!~ip{if(FNR<=1)printf start; else printf ","}\
    {printf end, $8,$1,$2,$3,$4,$5,$6,$7} END{print ";"}' ${log} | ${sql}

kpp
лейтенант
Сообщения: 613
Зарегистрирован: 2009-08-05 16:10:46
Откуда: Украина Днепропетровск-Киев
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение kpp » 2013-11-21 16:04:24

Можете считать меня занудой :pardon: , но.
По части:

Код: Выделить всё

if(FNR<=1)printf start; else printf ","
1.Зачем использовать printf вместо print без особой надобности?
2.Вы используете то NR, то FNR. В чем отличие знаете?
NR - сквозная нумерация строк, FNR - нумерация для каждого файла своя.
Если в AWK передается один файл - разницы нет.
FNR - работает не во всех версиях AWK.

А в целом - теперь оптимальный красивый код.
Разве что комментариев не хватает :roll:
Нет, ребята, я не гордый. Не загадывая вдаль, так скажу: зачем мне орден? Я согласен на медаль.

flash709
рядовой
Сообщения: 15
Зарегистрирован: 2013-07-09 11:58:50

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение flash709 » 2014-02-25 15:50:35

Народ, простите если было или направьте в нужную тему. Сразускажу весь обугуглился из читался нахрен. БОльно не пинайте, но спросить больше негде :(
Проблема с ng_ipacct

Код: Выделить всё

root@gw02:/usr/ports # service ng_ipacct start
ngctl: send msg: No such file or directory
ngctl: line 2: error in file
/usr/local/etc/rc.d/ng_ipacct: WARNING: netgraph node 'em1_ip_acct' did not created!
ЧТо имеем

Код: Выделить всё

root@gw02:/usr/ports # uname -a
FreeBSD #### 10.0-RELEASE FreeBSD 10.0-RELEASE #1: Thu Feb 20 11:00:52 MSK 2014     adm@####:/usr/obj/usr/src/sys/gw02  amd64
Ядро

Код: Выделить всё

options         IPFIREWALL
options         IPFIREWALL_FORWARD
options         IPFIREWALL_VERBOSE
options         IPFIREWALL_VERBOSE_LIMIT=100
options         IPFIREWALL_NAT
options			IPDIVERT
options         DUMMYNET
options         HZ="1000"
options         LIBALIAS

options         NETGRAPH
options         NETGRAPH_ETHER
options         NETGRAPH_IFACE
options         NETGRAPH_KSOCKET
options         NETGRAPH_SOCKET
options         NETGRAPH_TEE
makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
options 	SCHED_ULE		# ULE scheduler
Конфиг

Код: Выделить всё

# $FreeBSD: ports/net-mgmt/ng_ipacct/files/ng_ipacct.conf,v 1.6 2008/06/03 10:40:16 skv Exp $
#
# Please read and meditate on netgraph(4), ipacctctl(8) and ngctl(8).

# Enable ng_ipacct (i.e. enable run startup script "ng_ipacct.sh")
ng_ipacct_enable="YES"

# Enable kernel modules loading.
# On "ng_ipacct.sh start" all kernel modules specified
# in ${ng_ipacct_modules_list} will be loaded.
# Note: on "ng_ipacct.sh stop" only "ng_ipacct" will be unloaded.
ng_ipacct_modules_load="YES"

# Netgraph can load required ng_* modules automatically on the hook creation
# - except for "ng_ether". Generally, modules preloading is recommended.
# Do not add to this list modules which are statically compiled into kernel.
#ng_ipacct_modules_list="netgraph ng_ether ng_cisco ng_socket ng_tee ng_ipacct"
#ng_ipacct_modules_list="netgraph ng_ether ng_ipacct"

ng_ipacct_modules_list="ng_ipacct"

# List of monitored interfaces. For each interface additional vars must be
# specified in corresponding variables 'ng_ipacct_IFACE_*'.
# See examples below.
ng_ipacct_interfaces="em1"

ng_ipacct_default_ether_start='
	name ipfw: ipfw1

	mkpeer ipfw1: tee 100 left
	name ipfw1:100 %%iface%%_tee
	connect ipfw1: 100 200 rightngctl 

	mkpeer %%iface%%_tee: ipacct left2right %%iface%%_in
	name %%iface%%_tee:left2right ip_acct
	connect ip_acct: %%iface%%_tee: %%iface%%_out right2left
'

#	mkpeer %%iface%%: tee lower right
#	name %%iface%%:lower %%iface%%_tee
#	connect %%iface%%: lower upper left

#	mkpeer %%iface%%_tee: ipacct right2left %%iface%%_in
#	name %%iface%%_tee:right2left %%iface%%_ip_acct
#	connect %%iface%%_tee: %%iface%%_ip_acct: left2right %%iface%%_out


ng_ipacct_default_ether_stop='
	shutdown %%iface%%_ip_acct:
	shutdown %%iface%%_tee:
	shutdown %%iface%%:
'

ng_ipacct_bpf_ether_start='
	name ipfw: ipfw1

	mkpeer ipfw1: tee 100 left
	name ipfw1:100 %%iface%%_tee
	connect ipfw1: 100 200 right

	mkpeer %%iface%%_tee: ipacct left2right %%iface%%_in
	name %%iface%%_tee:left2right ip_acct
	connect ip_acct: %%iface%%_tee: %%iface%%_out right2left
'

ng_ipacct_bpf_ether_stop='
        shutdown %%iface%%_ip_acct:
        shutdown %%iface%%_bpf:
        shutdown %%iface%%_tee:
        shutdown %%iface%%:
'

ng_ipacct_em1_dlt="EN10MB"	# required line; see ipacctctl(8)
ng_ipacct_em1_threshold="30000"	# '5000' by default
ng_ipacct_em1_verbose="yes"	# 'yes' by default
ng_ipacct_em1_saveuid="no"	# 'no' by default
ng_ipacct_em1_savetime="yes"	# 'no' by default
ng_ipacct_em1_start=${ng_ipacct_default_ether_start}
ng_ipacct_em1_stop=${ng_ipacct_default_ether_stop}
ng_ipacct_em1_checkpoint_script="/usr/home/elpaco/scripts/ng_ipacct.sh em1"
			# this script is called on "stop" (to save accumulated 
			# data) or via "rc.d/ng_ipacct.sh checkpoint"
БЛИН ТЕМОЙ ПРОМОХНУЛСЯ! МОдеры перекиньте плиз в нужное место!

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35069
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение Alex Keda » 2014-03-02 19:00:34

нужное - это какое? =)
Убей их всех! Бог потом рассортирует...

SiAl
рядовой
Сообщения: 32
Зарегистрирован: 2012-05-25 10:32:00

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение SiAl » 2014-03-19 11:57:40

Редко кто делится полноценными скриптами по IPFW, а он довольно замороченный для понимания новичками. Далее выкладываю пару скриптов для изучения новичками, в одном объявляются все переменные, в том числе и по сетевым интерфейсам, а во втором сами правила, причем запуск возможен с различными ключами для соответствующих целей.
"-list" - для отображения правил
"-stat" - для статических правил
"-test" - для отладки правил
Первый: variables.sh

Код: Выделить всё

#!/bin/sh
WanIf=`netstat -rnf inet |awk '/default/{print $6}'`                            # Интерфейс WAN/oif (outside/внешний)
if  [ "${WanIf}" != "" ]; then
        WanGw=`netstat -rnf inet |awk '/default/{print $2}'`                    # WAN/oif (outside/внешний) Gateway/Шлюз по умолчанию
        #/sbin/ipfw -q add 1 pass icmp from any to any icmptypes 0,8,11
        #if  [ "${WanGw}" != "" ] && [ "`ping -i 0.1 -c 5 -t 1 ${WanGw} |awk '/100.0% packet loss/'`" = "" ]; then
        #/sbin/ipfw -q delete 1
        if  [ "${WanGw}" != "" ]; then
                WanIp=`ifconfig ${WanIf}|awk '/inet /{print $2}'`               # WAN/oif (outside/внешний) IP/адрес
                #WanIp=`ifconfig ${WanIf}| grep inet | awk '{print $2}'`        # WAN/oif (outside/внешний) IP/адрес
                WanNet=`netstat -rnf inet |grep ${WanIf}|awk '/ U /{print $1}'` # WAN/oif (outside/внешняя) Net/сеть
                #WanNet=`netstat -rnf inet |awk '/ U /&&/${WanIf}/{print $1}'`  # WAN/oif (outside/внешняя) Net/сеть
        fi
        LanIf=`netstat -rnf inet |grep -v ${WanIf}|awk '/ U /{print $6}'`       # Интерфейс LAN (inside/внутренний)
        if  [ "${LanIf}" != "" ]; then
                LanIp=`ifconfig ${LanIf} |awk '/inet /{print $2}'`              # LAN/iif (inside/внутренний) IP/адрес
                #WanIp=`ifconfig ${LanIf}| grep inet | awk '{print $2}'`        # LAN/iif (inside/внутренний) IP/адрес
                LanNet=`netstat -rnf inet |grep ${LanIf}|awk '/ U /{print $1}'` # LAN/iif (inside/внутренняя) Net/сеть
                #WanNet=`netstat -rnf inet |awk '/ U /&&/${LanIf}/{print $1}'`  # LAN/iif (inside/внутренняя) Net/сеть
        fi
        echo Var1 ${WanIf} ${WanIp} ${WanGw} ${WanNet} ${LanIf} ${LanIp} ${LanGw} ${LanNet}  > /tmp/firevall
else
	WanIf="rl0"								# WAN Интерфейс	(outside/внешний)
	WanIp="77.37.166.92"							# WAN IP-адрес	(outside/внешний)
	WanGw="77.37.166.1"							# WAN Шлюз	(outside/внешний)
	WanNet="77.37.166.0/23"							# WAN IP-сеть	(outside/внешний)
	LanIf="lan0"								# LAN Интерфейс	(inside/внутренний)
	LanIp="192.168.0.5"							# LAN IP-адрес	(inside/внутренний)
	#LanGw="192.168.1.5"							# LAN Шлюз	(inside/внутренний)
	LanNet="192.168.0.0/24"							# LAN IP-сеть	(inside/внутренняя)
        echo Var2 ${WanIf} ${WanIp} ${WanGw} ${WanNet} ${LanIf} ${LanIp} ${LanGw} ${LanNet}
fi
LoopIf="lo0"								# LoopBack интерфейс (петля)
LoopIp="127.0.0.1"							# LocalHost IP
LoopNet="127.0.0.0/8"							# Сеть LocalHost(Подсеть для коммуникаций внутри хоста)
DmzIf="dmz0"								# DMZ Интерфейс	(демилитаризованная зона трехдомного типа
#DmzIp="172.16.1.1"							# DMZ IP-адрес	(демилитаризованная зона)
#DmzGw="172.16.1.1"							# DMZ Шлюз	(демилитаризованная зона)
DmzNet="172.16.1.0/28"							# DMZ IP-сеть	(демилитаризованная зона) 172.16.1.0-172.16.1.6
#PppIf="ng0"								# PPP Интерфейс	(PPPoE VPN клиент)
#PppIp="77.37.166.92"							# PPP IP-адрес	(PPPoE VPN клиент)
#PppGw="77.37.166.1"							# PPP Шлюз	(PPPoE VPN клиент)
#PppNet="77.37.166.0/23"						# PPP IP-сеть	(PPPoE VPN клиент)
VpnIf="ng*"								# VPN Интерфейс	(PPTP VPN сервер)
VpnGv="192.168.1.232"							# VPN IP-адрес	(PPTP VPN шлюз)
VpnNet="192.168.1.232/29"						# VPN IP-сеть	(PPTP VPN подсеть) 192.168.1.233-192.168.1.238
# При включении PPTP VPN сервера, накладывается ограничение на диапазон IP локальной сети
LanNet="$LanNet{1-231}"							# LAN IP-сеть	(inside/внутренняя) 192.168.1.1-192.168.1.231
OvpnIf="tun0"								# OVPN Интерфейс(Open VPN сервер)
OvpnIp="192.168.2.1"							# OVPN IP-адрес	(Open VPN шлюз)
OvpnNet="192.168.2.0/24"						# OVPN IP-сеть	(Open VPN подсеть)
# Зарезервированные по RFC 791 адреса которые не должны быть глобально маршрутизируемыми
OwnNet="0.0.0.0/8"							# "Своя" сеть (для локального использования на хосте при создании сокетов IP)
MCastNet="224.0.0.0/3"							# Class D, E multicast (общегрупповое вещание)
BCastNet="255.255.255.255"						# Broadcast
PrivNet="10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16"			# RFC 1918 - Приватные сети
DenyNet=$OwnNet", "$PrivNet						# Запрещенные сети
DenyNet=$DenyNet", 169.254.0.0/16"					# IANA - Канальные (link-local) адреса (IP сеть авто-конфигурации машин без DHCP)
DenyNet=$DenyNet", 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24"	# Для примеров в документации.
DenyNet=$DenyNet", 204.152.64.0/23"					# Sun Microsystems cluster interconnect (соединения кластеров)
DenyNet=$DenyNet", 240.0.0.0/4"						# Зарезервировано для использования в будущем
AdminHost="192.168.1.10,192.168.1.20,192.168.0.10,192.168.0.20"					# Компьютеры локальной сети, которым разрешен привелегированный доступ
DenyHost="192.168.1.30,192.168.1.40"					# Компьютеры локальной сети, которым запрещен доступ в internet
PubPort="0-1023"	# RFC 4340 Общеизвестные порты используемые процессами системы или прикладными программами, запущенные привилегированными пользователями
RegPort="1024-49151"	# RFC 4340 Зарегистрированные порты используемые процессами обычных пользователей или программами, запущенными обычными пользователями
DynPort="49152-65535"	# Клиентские порты используемые внутри закрытых сетей - для временного использования
# Запрещенные порты, по которым требуется посылка уведомления (RST), для ускорения работы приложений удаленного сервера/клиента
ResetPort="113"		# RFC 1413 запрет ident
# Запрещенные на отправку в Интернет порты Netbios/Samba
DenyPort="135"				# Windows (функция отображения конечных точек RPC) (COM/DCOM, DFS, журнал событий, репликация файлов, очереди сообщений и MsOutlook.)
DenyPort=$DenyPort",137,138,139,445"	# Netbios/Samba 137=name, 138=datagram, 139=session (браузер поиска компьютеров, службы совместного использования файлов, Net Logon и служба сервера), 445 (доступ к файлам, принтерам и другим сетевым ресурсам, межпроцессное взаимодействие)
DenyPort=$DenyPort",389,636"		# ldap и ldaps (sldap)
DenyPort=$DenyPort",520"		# RIP протокол дистанционно-векторной маршрутизации по умолчанию вещает в сеть свою полную таблицу маршрутизации раз в 30 секунд, довольно сильно нагружая низкоскоростные линии связи.
DmzUdp=""				# Открытые на серверах DMZ сервисы/порты "smtp/smtps,http,https,pop3/pop3s"
DmzTcp="25,465,80,443,110,995"		# Открытые на серверах DMZ сервисы/порты "smtp/smtps,http,https,pop3/pop3s"
WanUdp="1194"		                # Открытые на сервере сервисы/порты "openvpn" за исключением ssh
#WanTcp="25,80,110,1723"                 # Открытые на сервере сервисы/порты "ftp,smtp,http,pop3,pptp" за исключением ssh
WanTcp="1723"				# Открытые на сервере сервисы/порты "ftp,smtp,http,pop3,pptp" за исключением ssh
LanUdp="53,67,123,137,138"		# Открытые на сервере сервисы/порты "dns,dhcp,ntp,samba"
LanTcp="21,22,25,53,80,110,139,445,1723,1194,3306,5006,9091"   # Открытые на сервере сервисы/порты "ftp,ssh,smtp,dns,dhcp,http,pop3,pptp,openvpn,mysql,mpd5,transmission"
AdmTcp="20,22,25,465,53,110,1723"	# Разрешенные администраторам сервисы/порты "ftp-data,ftp,ssh,smtp/smtps,domain,http,https,pop3/pop3s,pptp,aol"
AdmUdp="53,443,955,1194"		# Разрешенные администраторам UDP сервисы/порты "domain,OpenVpn,OpenVpn"
UsrUdp="123"				# Разрешенные пользователям сервисы/порты "ftp,http,https,aol"
UsrTcp="21,80,443,8080,5190"		# Разрешенные пользователям сервисы/порты "ftp,http,https,aol"
BsdTcp="5999"            		# Разрешенные Jail серверам сервисы/порты "CVSup"
Второй: firewall.sh

Код: Выделить всё

#!/bin/sh
## Сброс и инициализация переменных, ограничений, очередей, таблиц, функций ###
#- Инициализация переменных скрипта ------------------------------------------#
ssys="set 0"; sbug="set 29"; sfnp="set 30"								# $ssys-обязательные, $sbug-отладка, $sfnp-fingerprinting/antispoofing
swan="set 1"; sdmz="set 2"; sppp="set 3"								# Правила на внешних интерфейсах $swan-WAN, $sdmz-DMZ, $sppp-PPP,
slan="set 4"; svpn="set 5"; sovpn="set 6"					 			# Правила на внутренних интерфейсах $slan-LAN, $svpn-VPN, $sovpn-OVPN
snat="set 10"; spip="set 11"; sque="set 12"								# Правила $snat=NAT, $spip=Pipe, $sque=Queue
l0=""; l1="log logamount 10"; l2="log logamount 100"; l3="log logamount 1000"				# Количество записей по правилу
inc=10;      SStart=100;  SysEnd=65000									# Значение шага динамической генерации номеров правил. Стартовое значение счетчика первичных и завершающих павил.
WanIn=1000;  DmzIn=2000;  PppIn=3000;  LanIn=4000;  VpnIn=5000;  OvpnIn=6000				# Стартовое значение счетчика правил по каждому интерфейсу для ф-ии ip_input()
WanOut=1500; DmzOut=2500; PppOut=3500; LanOut=4500; VpnOut=5500; OvpnOut=6500				# Стартовое значение счетчика правил по каждому интерфейсу для ф-ии ip_output()
. /etc/ipfw/variables.sh										# Запуск скрипта установки и инициализации переменных
#- Инициализация функций -----------------------------------------------------#
dyncmd () { eval ${fwcmd} add \$${1} ${@##${1}}; eval ${1}=$((${1}+${inc})); }				# Функция динамичекой генерации номеров правил 
setup_loopback () {											# Функция обязательных правил LoopBack интерфейса
	dyncmd "SStart" $ssys allow ip  from any			to any via ${LoopIf}		# Трафик через LoopBack интерфейс $LoopIf
	dyncmd "SStart" $ssys deny  ip  from any			to ${LoopNet}			# Запрет трафика на подсеть хоста на всех интерфейсах
	dyncmd "SStart" $ssys deny  ip  from ${LoopNet}		to any					# Запрет трафика из подсети хоста на всех интерфейсах
}

natWanIn ()  {		# Пример: natWanIn "$l1" "tcp" "192.168.1.10" "3389" "10389" "$sl2"		# Функция создания комплекта правил для проброса порта с внешнего интерфейса на адрес локальной сети
        dyncmd "WanIn"  $snat nat 1 $1 $2 from any to ${WanIp} $5 in  recv ${WanIf} $6
        dyncmd "WanOut" $snat nat 1 $1 $2 from $3 $4 to any out xmit ${WanIf} established
        dyncmd "LanIn"  $snat allow $1 $2 from $3 $4 to any in  recv ${LanIf}
        dyncmd "LanOut" $snat allow $1 $2 from any to $3 $4 out xmit ${LanIf}
}
natLanOut ()  {		# Пример: #natLanOut "$l1" "tcp" "192.168.1.10" "87.250.250.203" "9595" "$sl6"	# Функция создания комплекта правил для выхода в интернет с локальной сети 
        local notLanIp=$4; local setEstablished="established"
        if [ "${6##setup*}" != "" ]; then setEstablished=""; fi
        if [ "$4" == "any" ]; then notLanIp="not ${LanIp}"; fi
        dyncmd "WanIn" nat 1 $1 $2 from $4 $5 to ${WanIp} in recv ${WanIf} $setEstablished
	#dyncmd "WanIn"  $snat check-state
        dyncmd "WanOut" skipto $((${WanOut}+${inc})) $1 $2 from $3 to $4 $5 out xmit ${WanIf} $6
	#dyncmd "WanIn"  $snat deny  $1 $2 from $3 $4        to any in  recv ${WanIf} established
	#dyncmd "WanIn"  $snat deny  $1 $2 from any          to any in  recv ${WanIf}
	#dyncmd "WanOut" $snat deny  $1 $2 from any          to any out xmit ${WanIf}
        dyncmd "WanOut" nat 1 $1 $2 from $3 to $4 $5 out xmit ${WanIf}
        dyncmd "LanIn"  allow $1 $2 from $3 to $notLanIp $5 in recv ${LanIf}
        dyncmd "LanOut" allow $1 $2 from $notLanIp $5 to $3 out xmit ${LanIf}
}
configMini () {												# Функция создания минимально-достаточного набора проверенно-работающих статических правил
	setup_loopback													# Добавление обязательных правил LoopBack интерфейса
	dyncmd "SStart" $ssys check-state										# Разрешение установленных соединений
	dyncmd "WanIn"  $swan fwd ${LoopIp},22 $l1 tcp from any to ${WanIp} "10122" 	in  recv ${WanIf} $ks		# Разрешение подключения по SSH(22) из интернета
	dyncmd "WanIn"  $swan fwd ${LoopIp},21 $l1 tcp from any to ${WanIp} "10121" 	in  recv ${WanIf} $ks		# Разрешение подключения по FTP(21) из интернета
	dyncmd "WanIn"  $swan fwd ${LoopIp},1194 $l1 tcp from any to ${WanIp} "10194 " 	in  recv ${WanIf} $ks		# Разрешение подключения по OpenVPN(1194) из интернета
	dyncmd "WanIn"  $sfnp deny  $l1 ip   from "'table(1)'" 	to any			in  recv ${WanIf}		# Запрет не маршрутизируемого трафика
	dyncmd "WanIn"  $swan allow $l1 icmp from any		to ${WanIp}		in  recv ${WanIf} icmptypes "8"	# Разрешение входящих пингов (RFC 792 ICMP)
	for i in `echo ${WanTcp}|sed 's/,/ /g'`;  do									# Разрешение подключений к серверу из интернета на разрешенные порты
	dyncmd "WanIn"  $swan allow $l1 tcp  from any 		to ${WanIp} $i 		in  recv ${WanIf} ; done	#
	dyncmd "WanOut" $swan allow $l1 ip   from me		to any			out xmit ${WanIf} $ks		# Разрешение серверу выходить в интернет
	dyncmd "WanIn"  $snat nat 1 $l1 ip   from any 		to any 			in  recv ${WanIf}		# Включение NAT-а для всех подключений на внешнем интерфейсе
	dyncmd "WanOut" $snat nat 1 $l1 ip   from any 		to any 			out xmit ${WanIf}		#
	dyncmd "LanIn"  $slan allow $l1 ip   from any	 	to any			in  recv ${LanIf}		# Разрешение все для всех на внутреннем интерфейсе
	dyncmd "LanOut" $sbug allow $l1 ip   from any		to any			out xmit ${LanIf}		# 
	dyncmd "VpnIn"  $svpn allow $l1 ip   from ${VpnNet}	to ${LanNet}		in  recv ${VpnIf} $ks		# Разрешение из VPN сети в локалку
	dyncmd "OvpnOut" $sovpn allow $l1 ip from ${OvpnNet}	to ${LanNet}		in  recv ${OvpnIf} $ks		# Разрешение "все для всех" из VPN сети
}
deny_fnp_spoof ()  {											# Функция защиты от fingerprinting и antispoofing на входящем трафике WAN
#dyncmd "WanIn" $sfnp deny  $l1 ip   from any 		to not ${WanIp}		in  recv ${WanIf}					# Анти спуфинг - Запрет пакетов адресованных не серверу
dyncmd "WanIn" $sfnp deny  $l1 ip   from "'table(1)'" 	to any			in  recv ${WanIf}					# Запрет не маршрутизируемого трафика
dyncmd "WanIn" $sfnp deny  $l1 ip   from any		to ${WanIp}		in  recv ${WanIf} ipoptions ssrr			# Запрет пакетов с нестандартными IP-опциями
dyncmd "WanIn" $sfnp deny  $l1 ip   from any		to ${WanIp}		in  recv ${WanIf} ipoptions lsrr
dyncmd "WanIn" $sfnp deny  $l1 ip   from any		to ${WanIp}		in  recv ${WanIf} ipoptions rr
dyncmd "WanIn" $sfnp deny  $l1 ip   from any		to ${WanIp}		in  recv ${WanIf} ipoptions ts				# Запрет пакетов с Timestamp
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags !syn, !ack, !rst		# Запрет NULL-пакетов (без единого флага) - второй тест nmap
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags syn, fin, urg, psh, !ack	# Запрет XMAS-пакетов - третий тест nmap
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags syn, fin, !ack
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags fin, urg, psh, !ack		# Седьмой тест nmap
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags fin, !ack
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags urg, !ack
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags psh, !ack
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags fin, syn, rst, psh, ack, urg	# Запрет X-сканирования:
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} tcpflags !fin, !syn, !rst, !psh, !ack, !urg	# Запрет NULL-сканирования:
dyncmd "WanIn" $sfnp deny  $l1 tcp  from any		to ${WanIp}		in  recv ${WanIf} not established tcpflags fin		# Запрет FIN-сканирования:
dyncmd "WanIn" $sfnp deny  $l1 ip   from any		to ${WanIp}		in  recv ${WanIf} not verrevpath in			# Защита от спуфинга
#${fwcmd} set disable $sfnp								# enable/disable правил ОТЛАДКА. 
}
#- Разделение на отладку и применение правил----------------------------------#
if [ "${1}" == "-list" ]; then fwcmd="echo ipfw"					# Запуск скрипта c опцией "-list" - для отображения правил
if [ "${2}" != "-stat" ]; then ks="keep-state"; fi					# Запуск скрипта c опцией "-stat" - для статических правил
elif [ "${1}" == "-test" ]; then fwcmd="/sbin/ipfw -n"					# Запуск скрипта c опцией "-test" - для отладки правил
if [ "${2}" != "-stat" ]; then ks="keep-state"; fi					# Запуск скрипта c опцией "-stat" - для статических правил
else											# Запуск скрипта в рабочем режиме - для применения правил
if [ "${1}" != "-stat" ]; then ks="keep-state"; fi					# Запуск скрипта c опцией "-stat" - для статических правил
#- Сброс(удаление) всех правил, пайпов, очередей, таблиц ---------------------#
fwcmd="/sbin/ipfw -q"									# Подавление информационных сообщений при добавлении правил
${fwcmd} -f flush                							# Сброс правил
#${fwcmd} -f pipe flush									# Сброс ограничителей ширины канала
#${fwcmd} -f queue flush								# Сброс очередей
${fwcmd} -f table all flush								# Сброс всех таблиц
for i in `${fwcmd} nat show config |awk '{print $3}'`; do ${fwcmd} nat $i delete; done	# Сброс всех правил нат
#- Инициализация переменных SYSCTL -------------------------------------------#
#${fwcmd} -f enable one_allow			#sysctl net.inet.ip.fw.one_allow=1	# Пакеты, перенаправляемые мостом, обрабатываются ipfw один раз
${fwcmd} -f enable verbose			#sysctl net.inet.ip.fw.verbose=1	# Включение выдачи более подробных сообщений. 
${fwcmd} -f enable debug			#sysctl net.inet.ip.fw.debug=1		# Включение отладочных сообщений.
#sysctl net.inet.ip.fw.verbose_limit=0							# Ограничение количества сообщений. 0 - без ограничений
#sysctl net.inet.ip.fw.autoinc_step=10		# inc=10				# Установка разности между номерами правил при их автогенерации
#sysctl net.inet.ip.fw.default_to_accept=0						# Правило по умолчанию, 0-доступ запрещен
#- Инициализация таблиц ------------------------------------------------------#
for i in ${DenyNet};  do ${fwcmd} table 1 add $i; done					# Создание таблицы(1) приватных сетей
for i in `echo ${DenyHost}|sed 's/,/ /g'`; do ${fwcmd} table 2 add $i; done		# Создание таблицы(2) блокированных хостов
for i in `echo ${AdminHost}|sed 's/,/ /g'`; do ${fwcmd} table 3 add $i; done		# Создание таблицы(3) административных хостов
#- Инициализация объектов NAT, pipe, queue -----------------------------------#
${fwcmd} nat 1 config log if ${WanIf} reset deny_in same_ports unreg_only redirect_port tcp 192.168.1.10:3389 10389 	# Включить nat 1 на внешнем интерфейсе, Включить редирект на внутренний RDP
#${fwcmd} pipe 1 config bw 7Mbit/s queue 10						# исходящая
#${fwcmd} pipe 2 config bw 7Mbit/s queue 10						# входящая
#${fwcmd} queue 1 config mask src-ip 0xffffffff pipe 1 queue 70 gred 0.002/15/35/0.2	# 
#${fwcmd} queue 2 config mask dst-ip 0xffffffff pipe 2 queue 70 gred 0.002/15/35/0.2	# 
if [ "${1}" == "-mini" ]; then configMini; exit; fi					# Запуск скрипта c опцией "-mini" - для минимальных правил
fi
#- Инициализация переменных и правил для динамических правил -----------------#
if [ "$ks" != "" ]; then sks="setup $ks"; sl="setup limit src-addr";
sl2="$sl 2"; sl4="$sl 8"; sl6="$sl 32"; sl7="$sl 64"; sl8="$sl 128";			# 1-1/2-2/3-4/4-8/5-16/6-32/7-64/8-128
dyncmd "SStart" $ssys check-state ; fi							# Разрешение установленных соединений
###############################################################################

## Правила IPFW ###############################################################
#-($SStart)  Стартовые правила -----------------------------------------------#
setup_loopback														# Обязательные правила LoopBack интерфейса
#-(00300) Подсчет всего трафика в интернет и обратно -------------------------#
#dyncmd "SStart" $ssys count $l0 ip  from ${WanIp}		to not ${LanNet} out via $WanIf
#dyncmd "SStart" $ssys count $l0 ip  from not ${LanNet}	to ${WanIp}	in via $WanIf
#-(00400) Правила распределения по ф-ям ip_input/ip_output и интефейсам ------#
dyncmd "SStart" $ssys skipto ${WanIn} ip   from any 		to any			in  via ${WanIf}		# ip_input()
dyncmd "SStart" $ssys skipto ${DmzIn} ip   from any 		to any			in  via ${DmzIf}	
#dyncmd "SStart" $ssys skipto ${PppIn} ip   from any 		to any			in  via ${PppIf}	
dyncmd "SStart" $ssys skipto ${LanIn} ip   from any 		to any			in  via ${LanIf}	
dyncmd "SStart" $ssys skipto ${VpnIn} ip   from any 		to any			in  via ${VpnIf}	
dyncmd "SStart" $ssys skipto ${OvpnIn} ip   from any 		to any			in  via ${OvpnIf}	
dyncmd "SStart" $ssys skipto ${WanOut} ip   from any 		to any			out via ${WanIf}		# ip_output()
dyncmd "SStart" $ssys skipto ${DmzOut} ip   from any		to any			out via ${DmzIf}	
#dyncmd "SStart" $ssys skipto ${PppOut} ip   from any		to any			out via ${PppIf}	
dyncmd "SStart" $ssys skipto ${LanOut} ip   from any 		to any			out via ${LanIf}	
dyncmd "SStart" $ssys skipto ${VpnOut} ip   from any 		to any			out via ${VpnIf}	
dyncmd "SStart" $ssys skipto ${OvpnOut} ip   from any 		to any			out via ${OvpnIf}	

#-($WanIn)  Трафик WAN входящий - in recv ${WanIf} ---------------------------#
deny_fnp_spoof														# Защита от fingerprinting и antispoofing на входящем трафике WAN --#
dyncmd "WanIn"  $swan fwd ${LoopIp},22 $l1 tcp from any to ${WanIp} "10122" 	in  recv ${WanIf} $sl2                  # Разрешение подключения по SSH(22) из интернета
dyncmd "WanIn"  $swan fwd ${LanIp},21 $l1 tcp from any 	to ${WanIp} "10121" 	in  recv ${WanIf} $sl2                  # Разрешение подключения по FTP(21) из интернета
dyncmd "WanIn"  $swan fwd ${LoopIp},1194 $l1 tcp from any to ${WanIp} "10194 " 	in  recv ${WanIf} $sl2                  # Разрешение подключения по OpenVPN(1194) из интернета
dyncmd "WanIn"  $swan fwd 172.16.1.1,80 $l1 tcp from any to ${WanIp} "8080" 	in  recv ${WanIf} $sl8                  # Разрешение подключения по WWW(80) из интернета в зону DMZ
dyncmd "WanIn"  $swan fwd 172.16.1.1,80 $l1 tcp from any to ${WanIp} "80"	in  recv ${WanIf} $sl8			# Разрешение подключения по W
dyncmd "WanIn"  $swan allow $l1 icmp from any		to ${WanIp}		in  recv ${WanIf} icmptypes "8" $ks	# Разрешение входящих пингов (RFC 792 ICMP)
dyncmd "WanIn"  $swan allow $l1 udp  from any 		to ${WanIp} "10413" 	in  recv ${WanIf} $ks			# Разрешение torrent - Transmission
dyncmd "WanIn"  $swan allow $l1 tcp  from any           to ${WanIp} "10413"     in  recv ${WanIf} $sks			# Разрешение torrent - Transmission
#dyncmd "WanIn"  $swan allow $l1 udp  from any "67"	to ${WanIp} "68"	in  recv ${WanIf} $ks	# DHCP (UDP 77.37.166.92:68 77.37.128.2:67 out via rl0)
#dyncmd "WanIn"  $swan allow $l1 ospf from any		to any			in  recv ${WanIf}			# 
for i in `echo ${WanTcp}|sed 's/,/ /g'`;  do										# Разрешение подключений к серверу из интернета на разрешенные порты
dyncmd "WanIn" $swan allow $l1 tcp  from any to ${WanIp} $i in recv ${WanIf} $sl7; done
#-($WanIn) NAT входящего трафика WAN - in recv ${WanIf} ----------------------#
dyncmd "WanIn" $snat nat 1 $l1 gre  from any		to ${WanIp}		in  recv ${WanIf}			# compressed PPP data
natWanIn "$l1" "tcp" "192.168.1.10" "3389" "10389" "$sl2"
#-($WanOut) Трафик WAN исходящий - out xmit ${WanIf} -------------------------#
dyncmd "WanOut" $sfnp deny  $l1 ip   from any 		to any ${DenyPort}	out xmit ${WanIf}			# Запрет отправки в Интернет пакетов Netbios/Samba
dyncmd "WanOut" $swan allow $l1 udp  from ${WanIp} "68"	to any "67"		out xmit ${WanIf} $ks	# DHCP (UDP 77.37.166.92:68 77.37.128.2:67 out via rl0)
dyncmd "WanOut" $swan allow $l1 udp  from ${WanIp}	to any "53"		out xmit ${WanIf} $ks			# Разрешение DNS запросов 53-"domain"
#dyncmd "WanOut" $swan allow $l1 tcp  from ${WanIp}	to any "53"		out xmit ${WanIf} $sks			# Разрешение DNS запросов
dyncmd "WanOut" $swan allow $l1 udp  from ${WanIp}	to any "123"		out xmit ${WanIf} $ks			# Разрешение NTP запросов
dyncmd "WanOut" $swan allow $l1 udp  from ${WanIp} "10413" to any		out xmit ${WanIf} $ks			# Разрешение torrent - Transmission
#dyncmd "WanOut" $sbug allow $l1 icmp from ${WanIp}	to any			out xmit ${WanIf} $ks			# ОТЛАДКА. Разрешение серверу ходить в инет
#dyncmd "WanOut" $sbug allow $l1 udp  from ${WanIp}	to any			out xmit ${WanIf} $ks			# ОТЛАДКА. Разрешение серверу ходить в инет
#dyncmd "WanOut" $sbug allow $l1 tcp  from ${WanIp}	to any			out xmit ${WanIf} $sks			# ОТЛАДКА. Разрешение серверу ходить в инет
#-($WanOut) NAT исходящего трафика WAN - out xmit ${WanIf} -------------------------#
dyncmd "WanOut" $snat nat 1 $l1 gre  from ${WanIp}	to any			out xmit ${WanIf}			# compressed PPP data
#-($WanOut) Трафик WAN с локальной сети в интернет - out recv ${LanIf} xmit ${WanIf}#
#dyncmd "WanOut" $swan allow $l1 tcp  from ${LanNet}	to any  "pptp"		out recv ${LanIf} xmit ${WanIf} $sks	# Разрешение VPN запросов Microsoft Point-to-Point Tunneling Protocol (PPTP)

#-($DmzIn)  Трафик DMZ входящий - in recv ${DmzIf} ---------------------------#
#dyncmd "DmzIn"  $sdmz nat 1 $l1 tcp from any "5999"	to ${WanIp} in recv rl0 established				# csup/cvsup
#dyncmd "DmzIn"  $sdmz nat 1 $l1 tcp from any		to ${WanIp} "6849152-65535" in recv rl0 established		# fetch FTP passive
#dyncmd "DmzIn"  $sbug allow $l1 icmp from any		to ${DmzNet}		in  recv ${DmzIf} $ks			# ОТЛАДКА. Разрешение серверу ходить в инет
#dyncmd "DmzIn"  $sbug allow $l1 udp  from any		to ${DmzNet}		in  recv ${DmzIf} $ks			# ОТЛАДКА. Разрешение серверу ходить в инет
#dyncmd "DmzIn"  $sbug allow $l1 tcp  from any           to ${DmzNet}            in  recv ${DmzIf} $sks			# ОТЛАДКА. Разрешение серверу
dyncmd "DmzIn"  $sdmz allow $l1 tcp  from any		to 172.16.1.1 "80"	in  recv ${DmzIf} $sks			# Разрешение подключений к WWW серверу
#-($DmzOut) Трафик DMZ исходящий - out xmit ${DmzIf} -------------------------#
dyncmd "DmzOut" $sdmz nat 1 $l1 icmp from ${DmzNet}     to any                  out xmit ${DmzIf} icmptypes "0,8" $ks   # Разрешение ping-ов из DMZ с
dyncmd "DmzOut" $sdmz allow $l1 icmp from ${DmzNet}	to any			out xmit ${DmzIf} icmptypes "0,8"	# Разрешение ping-ов из DMZ сети
#dyncmd "DmzOut" $sbug allow $l1 udp  from ${DmzNet}	to any			out xmit ${DmzIf} $ks			# ОТЛАДКА. Разрешение серверу ходить в инет
#dyncmd "DmzOut" $sbug allow $l1 tcp  from ${DmzNet}     to any                  out xmit ${DmzIf} $sks                  # ОТЛАДКА. Разрешение серверу
dyncmd "DmzOut" $sdmz nat 1 $l1 tcp  from 172.16.1.1	to any "21,80,443"	out xmit ${WanIf} $sks			# Разрешение серверу WWW подключаться на порты 21,80,443
dyncmd "DmzOut" $sdmz allow $l1 tcp  from 172.16.1.1 "80" to any		out xmit ${DmzIf}			# Разрешение серверу WWW подключаться на порты 21,80,443
dyncmd "DmzOut" $sbug allow $l1 udp  from ${LanIp} "53,123" to ${DmzNet}	out xmit ${DmzIf} $ks			# Разрешение DMZ сети обращаться к DNS и NTP
#-($DmzOut) Трафик DMZ с интернета в DMZ - out recv ${WanIf} xmit ${DmzIf} ---#

#-($PppIn)  Трафик PPP входящий - in recv ${PppIf} ---------------------------#
#dyncmd "PppIn" $snat nat 2 $l1 ip   from any		to ${PppIp}		in via ${PppIf}
#-($PppOut) Трафик PPP исходящий - out xmit ${PppIf} -------------------------#
#dyncmd "PppOut" $snat nat 2 $l1 ip   from ${LanNet}	to any			out via ${PppIf}
#-($PppOut) Трафик PPP с интернета в PPP - out recv ${WanIf} xmit ${PppIf} ---#

#-($LanIn)  Трафик LAN входящий - in recv ${LanIf} ---------------------------#	#- Транзитный трафик из локалки в интернет будет преобразован роутером в out xmit ${WanIf} и уже в таком виде попадает в NAT
#dyncmd "LanIn"  $sfnp deny  $l1 ip   from any		to not ${LanIp}		in  recv ${LanIf}			# Анти спуфинг - Запрет пакетов адресованных не серверу
#dyncmd "LanIn"  $sfnp deny  $l1 ip   from ${WanNet}	to any			in  recv ${LanIf}			# Анти спуфинг - Запрет перекрестных пакетов
dyncmd "LanIn"  $sfnp reset $l1 ip   from ${LanNet} 	to any ${ResetPort}	in  recv ${LanIf}			# Отвергать пакеты на данные порты с посылкой уведомлений
dyncmd "LanIn"  $slan deny  $l1 ip   from "'table(2)'" 	to not ${LanIp}		in  recv ${LanIf}			# Запрет доступа в internet заблокированным компьютерам локальной сети
dyncmd "LanIn"  $slan allow $l1 udp  from ${LanNet} "68" to ${LanIp} "67"    	in recv ${LanIf} $ks	# DHCP (UDP 192.168.1.10:68 192.168.1.5:67 in via em0)
dyncmd "LanIn"  $slan allow $l1 udp  from ${LanNet} "68" to ${BCastNet} "67" 	in recv ${LanIf}	# DHCP (UDP 192.168.1.10:68 255.255.255.255:67 in via em0)
dyncmd "LanIn"  $slan allow $l1 udp  from ${OwnNet} "68" to ${BCastNet} "67" 	in recv ${LanIf} 	# DHCP (UDP 0.0.0.0:68 255.255.255.255:67 in via em0)
dyncmd "LanIn"  $slan allow $l1 udp  from ${LanNet} 	to ${LanIp} "53"	in  recv ${LanIf} $ks			# Разрешение запросов к DNS серверу
dyncmd "LanIn"  $slan allow $l1 icmp from ${LanNet} 	to ${LanIp}		in  recv ${LanIf} icmptypes "0,3,4,8,11,12" $ks	# Разрешение из локалки Ping-а к серверу
dyncmd "LanIn"  $slan allow $l1 udp  from ${LanNet} 	to ${LanIp} ${LanUdp}	in  recv ${LanIf} $ks			# Разрешение входящих подключений к портам разрешенных сервисов сервера
dyncmd "LanIn"  $slan allow $l1 tcp  from ${LanNet} 	to ${LanIp} ${LanTcp}	in  recv ${LanIf} $sks			# Разрешение входящих подключений к портам разрешенных сервисов сервера
#dyncmd "LanIn"  $slan fwd {LoopIp},3128 $l1 tcp from ${LanNet} to not ${LanNet} "80,3128,8000,8001,8080,8081,443,21" in  recv ${LanIf} $sks
#-($LanOut) Трафик LAN исходящий - out xmit ${LanIf} -------------------------#
dyncmd "LanOut" $sbug allow $l1 ip   from me		to any			out xmit ${LanIf} $ks			# ОТЛАДКА. Серверу выход на внутреннем интерфейсе
#-($LanOut) NAT трафика с ${LanNet} в интернет - out xmit ${LanIf} -----------#
natLanOut "$l1" "udp"  "${LanNet}"  "any" "${UsrUdp}" "$ks"								# Разрешение локалке ходить в инет на разрешенные порты
natLanOut "$l1" "tcp"  "${LanNet}"  "any" "${UsrTcp}" "$sks"								# Разрешение локалке ходить в инет на разрешенные порты
natLanOut "$l1" "icmp" "'table(3)'" "any" ""           "$ks"								# Разрешение админам пинговать хосты в интернете
natLanOut "$l1" "udp"  "'table(3)'" "any" "${AdmUdp}" "$ks"								# Разрешение админам ходить в инет на разрешенные админские UDP порты
natLanOut "$l1" "tcp"  "'table(3)'" "any" "${AdmTcp}" "$sl2"								# Разрешение админам ходить в инет на разрешенные админские TCP порты
#-($LanOut) Трафик LAN с интернета в локальную сеть - out recv ${WanIf} xmit ${LanIf}#
#dyncmd "LanOut" $sbug allow $l1 tcp  from ${LanNet}	to any			out recv ${WanIf} xmit ${LanIf} $sks	# ОТЛАДКА.

#-($VpnIn)  Трафик VPN входящий - in recv ${VpnIf} ---------------------------#
#dyncmd "VpnIn"  $svpn allow $l1 ip   from any		to any verrevpath	via ${VpnIf}				# ОТЛАДКА. Разрешение "все для всех" из VPN сети
dyncmd "VpnIn" $svpn allow $l1 ip   from ${VpnNet}		to ${LanNet}		in  recv ${VpnIf} $ks		# Разрешение из VPN сети в локалку
#-($VpnOut) Трафик VPN исходящий - out xmit ${VpnIf} -------------------------#
#dyncmd "VpnOut" $svpn allow $l1 ip   from ${LanNet}		to ${VpnNet}		out xmit ${VpnIf}		# Разрешение из локалки в VPN сеть
#-($VpnOut) Трафик VPN с интернета на VPN - out recv ${WanIf} xmit ${VpnIf} --#

#-($OvpnIn)  Трафик OVPN входящий - in recv ${OvpnIf} ------------------------#
dyncmd "OvpnOut" $sovpn allow $l1 ip   from ${OvpnNet}		to ${LanNet}		in  recv ${OvpnIf} $ks		# Разрешение "все для всех" из VPN сети
#-($OvpnOut) Трафик OVPN исходящий - out xmit ${OvpnIf} ----------------------#
#dyncmd "OvpnOut" $sovpn allow $l1 ip   from ${LanNet}		to ${OvpnNet}		out xmit ${OvpnIf}		# ОТЛАДКА. Разрешение "все для всех" из VPN сети
#-($OvpnOut) Трафик OVPN с интернета на VPN - out recv ${WanIf} xmit ${VpnIf}-#

#dyncmd "SysEnd" $sbug allow $l1 ip   from any		to any							# ОТЛАДКА. Разрешение "все для всех" из VPN сети
dyncmd "SysEnd" $sbug deny  $l1 ip   from any		to any							# ОТЛАДКА. Запрет "все для всех" из VPN сети

# ===============================================================
if [ "${1}" == "-temp" ]; then sleep 300; exec $0 '-mini'; fi					# Запуск скрипта c опцией "-temp" - для отката на минимальный конфиг через 5 мин

SiAl
рядовой
Сообщения: 32
Зарегистрирован: 2012-05-25 10:32:00

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение SiAl » 2014-03-25 11:00:51

Появилась надобность рассортировать фотографии и видео полученные цифровыми аппаратами, покопался в инете на счет скриптов и на базе одного из найденных написал под свои потребности. Фотографии все хранились в десятках мест и имелись не только дубли, но и многочисленные варианты обработанных фотографий. Требовалось всю эту кучу рассортировать, удалить дубликаты, а обработанные файлы поместить во временную папку для дальнейшего разбора. В моем случае файлы для разбора копируются через самбу с включенными параметрами: dos charset = CP1251 unix charset = UTF-8 и данный скрипт не корректно обрабатывает имена файлов в кодировке CP1251, но мне это и не важно.

Код: Выделить всё

#п п?я?я?п?пҐя?п?п?.JPG --> 2008-04-21_15-56-06_п?п?я?я?п?пҐя?п?п?.JPG	# Console: KOI8-U Locale: CP1251
#Каштанчик.JPG --> 2008-04-21_15-56-06_ЊаштанчШЪ.JPG	# Console: UTF-8 Locale: CP1251
#Памятник.JPG --> 2008-04-21_14-07-28_ЏаУятнШЪ.JPG	# Console: UTF-8 Locale: CP1251
Во избежание проблем с windows системами все имена файлов и их расширений приводятся к верхнему регистру. Скрипт справился с более чем пятьюдесятью тысячами уникальных файлов не считая удаленных дублей.

Код: Выделить всё

#!/bin/sh
BASE_DIR="/shared/photo/import"		# Калог откуда будут разбираться файлы.
TEMP_DIR="/shared/photo/razbor"		# Каталог куда временно перемещаются дубли и "НЕ правильные" файлы для ручного разбора
#
SORT_DIR="/shared/photo/sorted"		# Каталог куда перемещаются "правильные" файлы
DATA_DIR="/shared/photo/source"		# Каталог куда перемещаются "RAW/сырцы" файлы
#
PRIV_DIR="/shared/photo/privat"		# Каталог для личных файлов

# Файлы [JPEG image data] содержащие [EXIF standard/JFIF standard/IPTC standard]
FILE_EXIF="JPG;JPE;JPEG;JFIF;MPO"
FILE_EXIF_DATA="JPEG_image_data"
# Файлы [raw image data]
FILE_RAW="ERF;CRW;CR2;NEF;NRW;MRW;PTX;PEF;ARW;SRW;SRF;SR2;ORF;RAF;DNG;DCR;KDC"
FILE_RAW_DATA="raw_image_data"
# Файлы содержащие [Apple QuickTime movie/MPEG sequence/Motion JPEG]
FILE_VIDEO="AVI;MOV;MPG;MP4;3GP"	#"ASF;ASX;BIK;DIVX;QT;IFO;MPEG;MPG4;OGM;RM;RMV;SMK;XVID;VOB;WM;WMV"
FILE_PICTURE="BMP;GIF;TIF;PNG;PSD"	#"ANI;CUR;DIB;EMF;EPS;ICN;ICL;ICO;IFF;LBM;RLE;PBM;PCD;PCX;PGM;PIC;PIX;PSP;TIFF;TGA;XIF;WMF;XBM;XPM"

# move_exiv_file
move_exiv_file(){
FILE_DATA=`echo $3 | sed 's/_/ /g'`; FILE_DIR=$1
#-----------------------------------------  Выполнение цикла по каждому расширению  -------------------------------------------#
for FILE_EXT in `echo $2| sed 's/;/ /g'` ; do
	#--------------------------  Выполнение цикла по каждому файлу с соответствующим расширением  -------------------------#
	find "$BASE_DIR" -name "*.$FILE_EXT" | sort | while read FILE_PATH ; do
		#-------------------------  Секция проверки файла на соответствие формату и EXIM даты  ------------------------#
		if ! file "$FILE_PATH" | grep -q "$FILE_DATA" ; then continue ; fi
		for EXIM_DATA in "Exif.Photo.DateTimeOriginal" "Exif.Photo.DateTimeDigitized" "Exif.Image.DateTime" ; do
			PHOTO_DATE=`exiv2 -g "$EXIM_DATA" -Pv "$FILE_PATH" | awk '{ print $1 }' | sed 's/[-_\.,/\]/:/g;s/[ ]//g;s/0000//g'` > /dev/null
			PHOTO_TIME=`exiv2 -g "$EXIM_DATA" -Pv "$FILE_PATH" | awk '{ print $2 }' | sed 's/[-_\.,/\]/:/g;s/[ ]//g'` > /dev/null
			if [ -n "$PHOTO_DATE" ] && [`echo -n "$PHOTO_DATE" | wc -c` -eq 10 ]; then break ; fi
		done
		#---------------------------  Переносятся только файлы с существующим и верным EXIF  --------------------------#
		if [ -z "$PHOTO_DATE" ] || [`echo -n "$PHOTO_DATE" | wc -c` -ne 10 ] ; then continue ; fi

		FILE_DATE=`stat -f%Sm -t'%Y:%m:%d' "$FILE_PATH"`; FILE_TIME=`stat -f%Sm -t'%H:%M:%S' "$FILE_PATH"` ; MOVE_DIR=""
		#-------  Преобразование формата даты - если год идет последним dd:mm:YYYY надо поменять на YYYY:mm:dd  -------#
		if [ `echo -n "$PHOTO_DATE" | awk -F: '{print $3}' | wc -c` -eq 5 ] ; then
			PHOTO_DATE=`date -j -f "%d:%m:%Y" "$PHOTO_DATE" "+%Y:%m:%d"`
			if [ "$PHOTO_DATE" != "$FILE_DATE" ] ; then MOVE_DIR="$TEMP_DIR" ; fi
			exiv2 -M"set $EXIM_DATA Ascii $PHOTO_DATE $PHOTO_TIME" "$FILE_PATH"
		fi
		#------------------  Заполнение обязательной Exif.Photo.DateTimeOriginal даты, если ее нет  -------------------#
		if [ "$EXIM_DATA" != "Exif.Photo.DateTimeOriginal" ] ; then exiv2 -M"set Exif.Photo.DateTimeOriginal Ascii $PHOTO_DATE $PHOTO_TIME" "$FILE_PATH" ; fi
		#-------  Корректировка даты файла в соотвествии с датой EXIF (exiv2 -M всегда меняет на текущую дату)  -------#
		if [ "$PHOTO_DATE" != "`stat -f%Sm -t'%Y:%m:%d' "$FILE_PATH"`" ] ; then exiv2 -T "$FILE_PATH" ; fi

		YEAR_DATE=`echo $PHOTO_DATE | awk -F: '{ print $1 }'` ; MONTH_DATE=`echo $PHOTO_DATE | awk -F: '{ print $2 }'`
		#-----------------------  Секция распределения файлов по каталогам и удаления дубликатов ----------------------#
		if [ `basename "$FILE_PATH"` = `basename "$FILE_PATH" | tr '[:lower:]' '[:upper:]'` ] ; then MOVE_DIR=${MOVE_DIR:-"$FILE_DIR"} ; else MOVE_DIR="$TEMP_DIR" ; fi
		FILE_NAME=`echo $PHOTO_DATE | sed 's/:/-/g'`"_"`echo $PHOTO_TIME | sed 's/:/-/g'`"_"`basename "$FILE_PATH" | tr '[:lower:]' '[:upper:]'`
		if [ -f "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ] ; then
			if diff -q "$FILE_PATH" "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME"; then rm "$FILE_PATH" ; continue ; fi
			if [ -f "$TEMP_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ] ; then
				if diff -q "$FILE_PATH" "$TEMP_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ; then rm "$FILE_PATH" ; continue ; fi
				continue ;
			fi
			MOVE_DIR=$TEMP_DIR
		fi

		#-------------------------------------  Создание структуры папок гггг/мм  -------------------------------------#
		if ! [ -d "$MOVE_DIR/$YEAR_DATE" ] ; then mkdir -pm 777 $MOVE_DIR/$YEAR_DATE ; fi
		if ! [ -d "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE" ] ; then mkdir -m 777 $MOVE_DIR/$YEAR_DATE/$MONTH_DATE ; fi

		#--------------------------------------  Непосредственно перенос файлов  --------------------------------------#
		#echo "mv -nv ($FILE_PATH) ($MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME)"	# Перенос фотографии
		mv -nv "$FILE_PATH" "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME"		# Перенос фотографии
	done
done
}

move_file(){
FILE_DIR=$1
#-----------------------------------------  Выполнение цикла по каждому расширению  -------------------------------------------#
for FILE_EXT in `echo $2 | sed 's/;/ /g'` ; do
	#--------------------------  Выполнение цикла по каждому файлу с соответствующим расширением  -------------------------#
	find $BASE_DIR -iname "*.$FILE_EXT" | sort | while read FILE_PATH ; do
		FILE_DATE=`stat -f%Sm -t'%Y:%m:%d' "$FILE_PATH"`; FILE_TIME=`stat -f%Sm -t'%H:%M:%S' "$FILE_PATH"` ; MOVE_DIR="$FILE_DIR"
		YEAR_DATE=`echo $FILE_DATE | awk -F: '{ print $1 }'` ; MONTH_DATE=`echo $FILE_DATE | awk -F: '{ print $2 }'`
		#----------------------  Секция распределения файлов по каталогам и удаления дубликатов  ----------------------#
		FILE_NAME=`echo $FILE_DATE | sed 's/:/-/g'`"_"`echo $FILE_TIME | sed 's/:/-/g'`"_"`basename "$FILE_PATH" | tr '[:lower:]' '[:upper:]'`
		if [ -f "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ] ; then
			if diff -q "$FILE_PATH" "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME"; then rm "$FILE_PATH" ; continue ; fi
			if [ -f "$TEMP_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ] ; then
				if diff -q "$FILE_PATH" "$TEMP_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME" ; then rm "$FILE_PATH" ; continue ; fi
				continue ;
			fi
			MOVE_DIR=$TEMP_DIR
		fi

		#-------------------------------------  Создание структуры папок гггг/мм  -------------------------------------#
		if ! [ -d "$MOVE_DIR/$YEAR_DATE" ] ; then mkdir -pm 777 $MOVE_DIR/$YEAR_DATE ; fi
		if ! [ -d "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE" ] ; then mkdir -m 777 $MOVE_DIR/$YEAR_DATE/$MONTH_DATE ; fi

		#--------------------------------------  Непосредственно перенос файлов  --------------------------------------#
		#echo "mv -nv ($FILE_PATH) ($MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME)"	# Перенос фотографии
		mv -nv "$FILE_PATH" "$MOVE_DIR/$YEAR_DATE/$MONTH_DATE/$FILE_NAME"		# Перенос фотографии
	done
done
}

# Сортировка файлов с EXIF информацией
#1) РАСШИРЕНИЕ в верхнем регистре - условно необработанные файлы
move_exiv_file $SORT_DIR $FILE_EXIF $FILE_EXIF_DATA
#2) расширение(в нижнем регистре) - условно файлы после фоторедакторов
move_exiv_file $SORT_DIR `echo $FILE_EXIF | tr '[:upper:]' '[:lower:]'` $FILE_EXIF_DATA
#3) RAW файлы
move_exiv_file $DATA_DIR $FILE_RAW $FILE_RAW_DATA
#4) VIDEO файлы
move_file "/shared/photo/video" $FILE_VIDEO
#5) PICTURE файлы
#move_file "/shared/photo/picture" $FILE_PICTURE


SiAl
рядовой
Сообщения: 32
Зарегистрирован: 2012-05-25 10:32:00

Re: Полезные скрипты наструганные на коленке.

Непрочитанное сообщение SiAl » 2014-11-20 17:33:41

Надо еще включить проверку наличия каталогов, а то висяки множатся бесконечно при отвале дисков и где то проблема с распознаванием форматов - с некоторых смартфонов ошибка. Еще немного нареканий на работу есть в плане преобразования времени - особенно когда дата по дефолту сброшена. Как руки дойдут перепишу и выложу.