ага.. оно почему-то то тормозит, то нет. я так понимаю, что на 3 неудачные попытки ip должен блокироваться? а на сколько? как вообще это должно работать? как обнулить все "плохие" ip?
Printable View
Блокируются входящие соединения во время, когда за последние 600 секунд имеется более 3 запросов на установления tcp сессии с одного ip. Попытки здесь не причем. Рабочая таблица находится в /proc/net/ipt_recent/SSH_ATTACKER
перед точно не надо, а вот после --- желательно
Правила выполняются одно за другим. Как только встречается правило, которое принимает окончательное решение, остальные не выполняются.
Он имел ввиду в post-firewall файле. А там как раз именно до этих строк нужно вставлять её. Мы ведь делаем -I (INSERT, вставка) на позицию 1 в цепочке и результат получится обратным(зеркальным) по отношению порядка следования команд в post-firewall.
gsnake, покажи чтоли таблицы (iptables -L -vn && iptables -L -vnt nat), а то непонятно, что там у тебя сейчас получилось. Ясно то, что до бана дело даже не доходит.
ps. Раскопал щас в man от iptables про то, как можно той таблицей манипулировать:
Соответственно DEFAULT на SSH_ATTACKER нужно заменитьCode:echo xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT
to Add to the DEFAULT list
echo -xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT
to Remove from the DEFAULT list
echo clear > /proc/net/ipt_recent/DEFAULT
to empty the DEFAULT list.
ok. я пользуюсь или vi или far для редактирования post-xxx файлов. то есть сейчас мой post-firewall выглядит так
#!/bin/sh
iptables -I INPUT -p tcp --dport хххх -j ACCEPT
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
iptables -t nat -I PREROUTING -i ! $3 -p tcp -m state --state NEW --dport хххх-m recent --set --name SSH_ATTACKER --rsource
iptables -I INPUT -i ! $3 -p tcp -m state --state NEW --dport хххх -m recent --update --seconds 600 --hitcount 3 --name SSH_ATTACKER --rsource -j DROP
logger '----iptables initialized----'
---------------------------------
Примечание - ХХХХ это мой порт. 8080 тоже открыт времменно (на всякий пожарный) :)
----------------------------
iptables -L -vn
Code:Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
4 200 DROP tcp -- !br0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:XXXX recent: UPDATE seconds: 600 hit_count: 3 name: SSH_ATTACKER side: source
211 22258 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080
362 38177 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:XXXX
2 152 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
16208 1453K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
1451 87060 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 state NEW
4658 1610K ACCEPT all -- br0 * 0.0.0.0/0 0.0.0.0/0 state NEW
441 159K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:67 dpt:68
88 20114 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 735 packets, 38292 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- br0 br0 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
519K 479M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 DROP all -- !br0 vlan1 0.0.0.0/0 0.0.0.0/0
70 5462 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate DNAT
Chain OUTPUT (policy ACCEPT 22838 packets, 3255K bytes)
pkts bytes target prot opt in out source destination
Chain MACS (0 references)
pkts bytes target prot opt in out source destination
Chain SECURITY (0 references)
pkts bytes target prot opt in out source destination
0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x16/0x02 limit: avg 1/sec burst 5
0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x17/0x04 limit: avg 1/sec burst 5
0 0 RETURN udp -- * * 0.0.0.0/0 0.0.0.0/0 limit: avg 5/sec burst 5
0 0 RETURN icmp -- * * 0.0.0.0/0 0.0.0.0/0 limit: avg 5/sec burst 5
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain logaccept (0 references)
pkts bytes target prot opt in out source destination
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 state NEW LOG flags 7 level 4 prefix `ACCEPT '
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain logdrop (0 references)
pkts bytes target prot opt in out source destination
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 state NEW LOG flags 7 level 4 prefix `DROP '
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
----
iptables -L -vnt nat
Code:Chain PREROUTING (policy ACCEPT 1358 packets, 157K bytes)
pkts bytes target prot opt in out source destination
4 200 tcp -- !br0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:XXXX recent: SET name: SSH_ATTACKER side: source
146 24959 VSERVER all -- * * 0.0.0.0/0 99.238.7.36
Chain POSTROUTING (policy ACCEPT 1576 packets, 96278 bytes)
pkts bytes target prot opt in out source destination
735 38292 MASQUERADE all -- * vlan1 !99.238.7.36 0.0.0.0/0
5 956 MASQUERADE all -- * br0 192.168.1.0/24 192.168.1.0/24
Chain OUTPUT (policy ACCEPT 1532 packets, 92894 bytes)
pkts bytes target prot opt in out source destination
Chain VSERVER (1 references)
pkts bytes target prot opt in out source destination
13 608 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6881 to:192.168.1.196:6881
36 3732 DNAT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:6881 to:192.168.1.196:6881
0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:31220 to:192.168.1.1:4662
0 0 DNAT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:31220 to:192.168.1.1:4662
Это похоже баг. Подробности расскажу позже.
зы. Через 600 секунд после старта роутера все должно заработать как надо.
В общем я думаю, что это этот баг тут воду мутит.
зы. Я попытался пересобрать прошивку, изменив код согласно приложенному к той статье патчу, но в связи со своими скромными познаниями наткнулся в результате на "insmod: unresolved symbol get_seconds" при попытке загрузить исправленный модуль. Так что подтвердить или опровергнуть выдвинутую мной гипотезу я не в состоянии.
Надо поискать эквивалент get_seconds в нашем ядре...
Нашел :) CURRENT_TIME ему имя. В общем выдрал я из ядра 2.4.35.3 ipt_recent.c и ipt_recent.h, наложил патч, что в той статье был и проблема исчезла. Не знаю, правильно ли я сделал, взяв из другой версии ядра эти файлы, но чёрт возьми это работает :) К тому же, судя по chanelog ядра, в ipt_recent были исправлены некоторые ошибки после версии 2.4.20.
Кто хочет, может попробовать приаттаченный модуль ipt_recent.o. Если позволит место во flashfs, то распакуйте файл .gz и запишите модуль .o допустим в /usr/local/lib и сохраните flashfs save && flashfs commit. В pre-boot соответственно строка загрузки будет такая: insmod /usr/local/lib/ipt_recent.o
upd:
До ввода команды flashfs commit, во избежание недоразумений убедитесь, что размер полученного flashfs не превышает 64К. Для этого после команды flashfs save (и до commit) обратите внимание на строку вида:
где значение, выделенное красным не должно превышать 65535. Если значение превышает максимальный размер, то откажитесь от данной затеи, НЕ делайте flashfs commit и удалите /usr/local/lib/ipt_recent.o.Code:-rw-r--r-- 1 root root 10710 Nov 16 15:24 /tmp/flash.tar.gz
Check saved image and type "/sbin/flashfs commit" to commit changes
upd2:
Можно также его слить с форума средствами роутера:
После только не забудьте проверить полученный размер с помощью ls -la /usr/local/lib/ipt_recent.o, он должен быть равен 14900 байт.Code:mkdir /usr/local/lib
wget 'http://wl500g.info/attachment.php?attachmentid=2005&d=1195170790' -O - | gzip -d > /usr/local/lib/ipt_recent.o
Code:-rw-r--r-- 1 root root 14900 Nov 16 01:03 /usr/local/lib/ipt_recent.o
Круто! :cool:Надо попробовать. Стоит ли упомянуть о том, что мой роутер не очень дружит с текущем временем.. Вот что я вижу в логе...
Dec 31 13:00:17 kernel: FAT: bogus logical sector size 20487
Dec 31 13:00:17 kernel: VFS: Can't find a valid FAT filesystem on dev 08:00.
Nov 15 09:24:06 ntp client: Synchronizing time with time.nist.gov ...
Nov 15 09:26:48 dnsmasq[81]: DHCPDISCOVER(br0) 00:02:72:5a:2f:e5
И то и другое неверно - ни 31 декабря ни 15 ноября в 9 часов..
gsnake
Минуты то правильные --- а чтобы часы были правильными надо выставлять корректную timezone в веб-ИФ. ntp сервер лучше ставить pool.ntp.org или ru.pool.ntp.org , хотя если с nist успешно соединяется, то это ничего не изменит.
Впрочем, для ipt_recent абсолютное время неважно. Ему нужны только относительные интервалы.
P.S. Прикольно --- действительно работает (по крайней мере меня банит). Могу добавить пару наблюдений, уточняющих поведение этой фичи:
1) Запрет происходит независимо от успешности/неуспешности логина.
2) Если --hitcount задан 3, то две попытки пропускаются третья банится.
3) Поскольку в приведенном примере используется параметр --update, то после третьей попытки будет баниться любые дальнейшие попытки в течение 600 секунд после последней попытки с этого IP. Для смягчения этого довольно жесткого правила можно вместо --update задать --rcheck, тогда время действия бана отсчитывается от первой попытки из трех. ( http://www.snowman.net/projects/ipt_recent/ )
Полагаю, что этот --hitcount можно увеличить где-то до 6, или даже до 11, чтобы не дай бог не обидеть себя любимого :). А то ведь иной раз и сам пароль перепутаешь, а с другой строрны иногда удобно организовать не одну сессию.
А нет ли возможности составить белый список адресов, на который данные правила не распространяются?
Неважно, если только оно не близкое к 1970-01-01 00:00:00 UTC, что для мной пропатченного ipt_recent является нулём со всеми вытекающими. Чтобы этого избежать в post-boot(или даже лучше в pre-boot) можно вставить допустим date 010101012000. Это поможет пропатченному, но не поможет оригинальному ipt_recent. В оригинальном ведется собственный отсчет, не зависящий от системного времени.
upd
Ну а какже. Перед дропающим правилом в INPUT можно вставить правило ACCEPT с источником ip=нужному адресу. Допустим, на примере моего post-firewall:
Code:#!/bin/sh
iptables -P INPUT DROP
iptables -D INPUT -j DROP
iptables -A INPUT -p tcp -s xx.xx.xx.xx --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW --dport 22 -m recent --set --name SSH_ATTACKER --rsource
iptables -A INPUT -p tcp -m state --state NEW --dport 22 -m recent --update --seconds 600 --hitcount 6 --name SSH_ATTACKER --rsource -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
- А зачем тогда PREROUTING используется? Если я запускаю dropbear на порту 8080 могу ли я использовать твой post-firewall (заменив соответственно 22 на 8080)? Или обязательно PREROUTING нужен?
- Кстати как часовой пояс правильно выставил все стало работать лучше (как описано у al37919 ). до этого было не 600 секунд а гораздо больше...
поменял - теперь пускает сколько хочешь.. =)
#!/bin/sh
iptables -P INPUT DROP
iptables -D INPUT -j DROP
iptables -A INPUT -p tcp -m state --state NEW --dport 8080 -m recent --set --name SSH_ATTACKER --rsource
iptables -A INPUT -p tcp -m state --state NEW --dport 8080 -m recent --update --seconds 600 --hitcount 6 --name SSH_ATTACKER --rsource -j DROP
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
Внимательнее, товарищи:)
#!/bin/sh
iptables -P INPUT DROP
iptables -D INPUT -j DROP
iptables -A INPUT -p tcp -m state --state NEW --dport 8080 -m recent --set --name SSH_ATTACKER --rsource
iptables -A INPUT -p tcp -m state --state NEW --dport 8080 -m recent --update --seconds 600 --hitcount 6 --name SSH_ATTACKER --rsource -j DROP
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
O, вот теперь получился любимый мной вариант, когда можно спокойно добавлять правила с помощью -A и не нужно монитор переворачивать вверх ногами, чтобы посмотреть в каком порядке они будут выполняться. :)
А если серьезно, то всегда надо проверять результат с помощью iptables -L [-t nat]
А если совсем по теме, то таблица постепенно заполняется. Эта штука работает часа 4, а в SSH_ATTACKER уже 3 записи включая мой тест. Аптайм к данному моменту 11 дней и надеюсь, что до своего возвращения из командировки он дойдет где-нибудь дней до 40. Сколько же записей будет в этой таблице и почему не удаляются бесполезные записи (те, срок давности по которым уже вышел). Ведь если гость с этого же адреса заглянет еще разок, то он будет добавлен с нуля без проблем. А ведь где-то это должно храниться, да и проверка идти по всем адресам --- лишние накладные расходы. Нет ли там варианта самоочистки от бесполезной информации. Или эта таблица из себя что то вроде лога представляет?
P.S. Ну да я понял, по крайней мере для ADSL соединения такая проблема не существует, т.к. при ежесуточном разрыве соединения iptables перезапускаются.
У меня в результате получился такой вариант начальной части post-firewall, который делает следующее:
1) Все действия по ssh порту вынесены в отдельный SSH_EVAL chain (насколько я понимаю так снижается количество проверок выполняемых iptables при выполнении _каждого_ соединения. Если запрос приходит на ssh порт, то на здоровье пусть хоть 100 правил проверяет...)
2) Созданы "белый" и "черный" списки адресов (какая польза от черного не знаю, но сделал для полноты картины). По тем IP которые находятся в этих списках решение принимается до проверки ipt_recent
3) Первое обновление recent перенесено из PREROUTING в тот же SSH_EVAL chain. Теперь оно выполняется только на тех соединениях, которые идут на ssh и не были отфильтрованы двумя вышеуказанными списками.
Файлы /usr/local/etc/ssh.allow & /usr/local/etc/ssh.deny содержат следующиее (сам адрес стоит в начале строки, потом пробел, потом любой комментарий):PHP Code:#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:usr/bin:/opt/sbin:/opt/bin:/opt/local/bin
logger "post-firewall started"
#this rule can be uncommented for the testing period
#iptables -A INPUT -p tcp --syn --dport 2222 -j ACCEPT
# set default policy
iptables -P INPUT DROP
# remove last default rule
iptables -D INPUT -j DROP
# ***ssh subsection begin***
SSH_PORT=22
SSH_ALLOW=/usr/local/etc/ssh.allow
SSH_DENY=/usr/local/etc/ssh.deny
# Create a new SSH_EVAL chain which will evaluate incoming connections to ssh server from WAN
iptables -N SSH_EVAL
# Transfer all ssh connections to the SSH_EVAL chain
iptables -A INPUT -p tcp --dport $SSH_PORT -j SSH_EVAL
# Evaluate incoming ssh connections through ssh.allow and ssh.deny lists
for i in `awk '{print $1}' $SSH_ALLOW`
do
iptables -A SSH_EVAL -p tcp --syn -s $i --dport $SSH_PORT -j ACCEPT
done
for i in `awk '{print $1}' $SSH_DENY`
do
iptables -A SSH_EVAL -p tcp --syn -s $i --dport $SSH_PORT -j DROP
done
# Block annoying intruder's attemtps (after --hitcount connections occured, wait --seconds after the last connection attempt)
# Remember, that both successful and unsuccessful connections are counted
iptables -A SSH_EVAL -i ! $3 -p tcp -m state --state NEW --dport $SSH_PORT -m recent --set --name SSH_ATTACKER --rsource
iptables -A SSH_EVAL -i ! $3 -p tcp -m state --state NEW --dport $SSH_PORT -m recent --update --seconds 600 --hitcount 4 --name SSH_ATTACKER --rsource -j DROP
# Accept the rest of ssh connections which were able to pass through the filtering
iptables -A SSH_EVAL -p tcp --syn --dport $SSH_PORT -j ACCEPT
# ***ssh subsection end***
...
Остальные правила post-firewall
P.S. Напоминаю, что модуль ipt_recent.o должен быть загружен в файле /usr/local/sbin/pre-bootPHP Code:12.34.56.78 разрешить/запретить доступ с одиночного IP
87.65.43.0/24 разрешить/запретить доступ с подсетки
Так что в файле pre-boot должно стоять либо ( для использования встроенного в прошивку ipt_recent ):
либо ( для использования ipt_recent от Mam(o)n : http://wl500g.info/showpost.php?p=69660&postcount=53 )PHP Code:insmod ipt_recent
PHP Code:date 010101012000
insmod /usr/local/lib/ipt_recent.o
Решение замечательное, правильное, оптимизированное. Всё организовано и упорядочено. Но заморочено :rolleyes: Его хорошо применять при динамически составляющихся и немалых по объему white и black списках, но если вего-лишь нужно за-white-листить пару айпи со своей работы то имхо проще пару команд в post-firewall добавить ;)
Спасибо, за добрые слова. Я в iptables начал не так давно что то понимать, так что мнение эксперта для меня важно.
Да и когда я основательно все перечислил у меня список почти на десяток получился :) Правда можно, конечно, оставить пару-тройку, зайдя с которых можно открыть на любой нужный --- но это как то неспортивно. :)
Да какой там из меня эксперт. Я то с *nix'ом сам всего лишь год с небольшим назад как познакомился и до сих пор в шоке от его потенциала. И всё благодаря этой коробочке с прошивкой Олега. Олегу за это отдельный респект :)
Нет, это не лог. Это так сказать проекция рабочей таблицы. Пока в тонкости работы ipt_recent я не углублялся, но поверхностно глянув в мануал, решения пока не увидел. Сходу в качестве варварского альтернативного способа можно в крон добавить команду очистки всей таблицы: echo clear > /proc/net/ipt_recent/SSH_ATTACKER. Или же можно периодично, с помощью того же крона, чистить таблицу избирательно, только устаревшие записи:
Где выделено красным это время жизни записи в секундах. То есть все записи, которые старше данного значения будут удалены. Данная конструкция будет работать только в пропатченном ipt_recent, где время считается в секундах относительно POSIX time. В оригинальном же модуле отсчет ведётся в попугаях (jiffies) и похоже, что относительно запуска программы.Code:cat /proc/net/ipt_recent/SSH_ATTACKER | awk -F '[ =]' -v date=$(date +%s) '{if(date-$6>600)system("echo -"$2" >/proc/net/ipt_recent/SSH_ATTACKER")}'
что-то не пойму как работает post-firewall... почему-то или openvpn работает в такой конфигурации или только ssh. (если меняю местами части для dropbear и openvpn) что же не так? вот мой post-firewall:
#!/bin/sh
iptables -P INPUT DROP
iptables -D INPUT -j DROP
# this is for dropbear and hit count
iptables -A INPUT -p tcp -m state --state NEW --dport 1111 -m recent --set --name SSH_ATTACKER --rsource
iptables -A INPUT -p tcp -m state --state NEW --dport 1111 -m recent --update --seconds 600 --hitcount 6 --name SSH_ATTACKER --rsource -j DROP
iptables -A INPUT -p tcp --dport 1111 -j ACCEPT
# this is for openvpn
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
iptables -t nat -I PREROUTING -i eth1 -p tcp --dport 8080 -j DNAT --to-destination \$4:8080
iptables -A INPUT -j DROP
iptables -I INPUT -i tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -j ACCEPT
iptables -I FORWARD -o tun0 -j ACCEPT
iptables -I OUTPUT -o tun0 -j ACCEPT
logger ----iptables initialized----
ssh не работает из-зи правила iptables -A INPUT -j DROP , которое не дает выполняться ничему после него. Его надо убрать, т.к. все равно стоит iptables -P INPUT DROP
В остальном разницы что где ставить вроде нет, т.к. ssh кусок добавляет правила в конец, а vpn кусок в начало...
вот строчка из /etc/pwd:
через телнет логинится нормально, а через putty/plink пишет access denied.Code:portforwarder:*********:98:98:root:/:/bin/ls
я пробовал опцию -N в plink, чтобы не запускать шелл, но не помогло.
1) /etc/passwd
2) login шелы должны быть перечислены в /etc/shells
странно, что через теленет --- ОК
спасибо, получилось. Сможет ли хакер взломать роутер, если будет знать пароль от portforwarder? Например копировать файлы по sftp? Мне надо, чтобы под этим юзером можно было только пробрасывать порты. Пароль мне придется сохранить на клиенте, откуда его могут украсть
/etc/passwd:
/etc/shells:Code:portforwarder:*******:98:98:nobody:/:/bin/nologin
Code:/bin/nologin
а можно вместо пароля сделать ключ и ассоциировать его с юзером portforwarder?
сломать просто если есть доступ на чтение к /etc/passwd и для шифрования используется алгоритм md5.
какой у нас исспользуется не скожу, посмотреть сейчас не могу.
посмотрел у нас не md5 :)
оказывается, если добавлять что-то в /etc/shells, надо сперва добавить туда /bin/sh, а не то перестает работать ssh
Пока не нашел, как привязать ключ к юзеру. (под админом я нормально логинюсь с помощью ключа)
http://www.nslu2-linux.org/wiki/HowT...orRemoteAccess
someone@hostname заменил на portforwarderQuote:
Once we have this we want to save our public key into the authorized keys file which can be done easily as follows (The key here has been shortened for display purposes. Your generated key will be a much longer string):
# echo ssh-rsa AAAAB3NzaC1yc2EAAAABIwAA......aJ3Wy+Ws4IZEgdJgPlTY UBWWtCWOGc= someone@hostname > authorized_keys
не работает.