Drop ALL the TCP connections (ESTABLISHED,RELATED) in Ubuntu
I’m facing a few hosts sending a flood of requests to my webserver (NGINX). I’m trying to block them via iptables, with ipset and a good old DROP rule. The rule is effective against NEW connections, but as soon as the kiddies can come in and set up an ESTABLISHED or RELATED connection, my DROP rule fails because my firewall also has a iptables -A INPUT -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT rule. The relevant section of my firewall config is:
# iptables -nL Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DROP all -- 0.0.0.0/0 0.0.0.0/0 match-set Blacklist src ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 DROP all -- 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
# ipset list Blacklist | grep
The question is: how can I KILL ALL the TCP connections, even the ESTABLISHED or RELATED ones? Things I’ve tried: Stop-wait-30-secs-start the webserver ( service nginx stop && sleep 30 && service nginx start ) — it was worth a shot, but since the connection is already ESTABLISHED, it persists. conntrack —flush and conntrack -F . No effect tcpkill : as long as I keep the process running it kinda works. But as soon as I close the process, the connection come back. I can’t really explain it conntrack -D —orig-src : the connection got deleted, but then appear back immeditaly. To check the connection I use:
netstat -putan | grep '' tcp 0 0 :443 :60763 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60807 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60545 ESTABLISHED 2372190/nginx: work tcp 0 0 :443 :59785 TIME_WAIT - tcp 0 0 :443 :59730 TIME_WAIT - tcp 0 0 :443 :59841 TIME_WAIT - tcp 0 0 :443 :60578 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60941 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59390 TIME_WAIT - tcp 0 0 :443 :59849 TIME_WAIT - tcp 0 0 :443 :60744 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59766 TIME_WAIT - tcp 0 0 :443 :59819 TIME_WAIT - tcp 0 0 :443 :60679 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59603 TIME_WAIT - tcp 0 0 :443 :60134 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60907 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59732 TIME_WAIT - tcp 0 0 :443 :60128 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60437 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59623 TIME_WAIT - tcp 0 0 :443 :59356 TIME_WAIT - tcp 0 0 :443 :60502 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59414 TIME_WAIT - tcp 0 0 :443 :60592 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59370 TIME_WAIT - tcp 0 0 :443 :60861 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59783 TIME_WAIT - tcp 0 0 :443 :59858 TIME_WAIT - tcp 0 0 :443 :59769 TIME_WAIT - tcp 0 0 :443 :60817 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59393 TIME_WAIT - tcp 0 0 :443 :60479 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60450 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59401 TIME_WAIT - tcp 0 0 :443 :60838 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60123 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60854 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59445 TIME_WAIT - tcp 0 0 :443 :59419 TIME_WAIT - tcp 0 0 :443 :60111 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60934 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60510 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60832 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60922 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60447 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60171 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60536 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59344 TIME_WAIT - tcp 0 0 :443 :59394 TIME_WAIT - tcp 0 0 :443 :59369 TIME_WAIT - tcp 0 0 :443 :60601 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59754 TIME_WAIT - tcp 0 5534 :443 :60954 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60895 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60236 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60099 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :59460 TIME_WAIT - tcp 0 0 :443 :60570 ESTABLISHED 2372191/nginx: work tcp 0 0 :443 :60555 ESTABLISHED 2372191/nginx: work
# conntrack -L --orig-src tcp 6 431977 ESTABLISHED src= dst= sport=62907 dport=443 src= dst= sport=443 dport=62907 [ASSURED] mark=0 use=1 tcp 6 431989 ESTABLISHED src= dst= sport=63062 dport=443 src= dst= sport=443 dport=63062 [ASSURED] mark=0 use=1 tcp 6 431976 ESTABLISHED src= dst= sport=62882 dport=443 src= dst= sport=443 dport=62882 [ASSURED] mark=0 use=1 tcp 6 299 ESTABLISHED src= dst= sport=63215 dport=443 src= dst= sport=443 dport=63215 [ASSURED] mark=0 use=1 tcp 6 431975 ESTABLISHED src= dst= sport=62869 dport=443 src= dst= sport=443 dport=62869 [ASSURED] mark=0 use=1 tcp 6 271 ESTABLISHED src= dst= sport=62800 dport=443 [UNREPLIED] src= dst= sport=443 dport=62800 mark=0 use=1 tcp 6 299 ESTABLISHED src= dst= sport=63211 dport=443 src= dst= sport=443 dport=63211 [ASSURED] mark=0 use=1 tcp 6 431977 ESTABLISHED src= dst= sport=62902 dport=443 src= dst= sport=443 dport=62902 [ASSURED] mark=0 use=1 tcp 6 431987 ESTABLISHED src= dst= sport=63038 dport=443 src= dst= sport=443 dport=63038 [ASSURED] mark=0 use=1 tcp 6 431999 ESTABLISHED src= dst= sport=63195 dport=443 src= dst= sport=443 dport=63195 [ASSURED] mark=0 use=1 tcp 6 431976 ESTABLISHED src= dst= sport=62887 dport=443 src= dst= sport=443 dport=62887 [ASSURED] mark=0 use=1 tcp 6 431988 ESTABLISHED src= dst= sport=63050 dport=443 src= dst= sport=443 dport=63050 [ASSURED] mark=0 use=1 tcp 6 431999 ESTABLISHED src= dst= sport=63201 dport=443 src= dst= sport=443 dport=63201 [ASSURED] mark=0 use=1 tcp 6 431998 ESTABLISHED src= dst= sport=63181 dport=443 src= dst= sport=443 dport=63181 [ASSURED] mark=0 use=1 conntrack v1.4.5 (conntrack-tools): 14 flow entries have been shown
Closing all TCP sockets on interface Down
I need to close all ongoing Linux TCP sockets as soon as the Ethernet interface drops (ie cable is disconnected, interface is down’ed and so on). Hacking into /proc seems not to do the trick. Not found any valuable ioctl’s. Doint it by hand at application level is not what I want, I’m really looking for a brutal and global way of doing it. Did anyane experienced this before and willing to share his foundings ?
2 Answers 2
The brutal way which avoids application level coding is hacking your kernel to activate TCP keepalive with a low timeout for all your connections.
Thanks for your suggestion. I tried the following : sysctl -w \ net.ipv4.tcp_keepalive_time=15 \ net.ipv4.tcp_keepalive_intvl=5 \ net.ipv4.tcp_keepalive_probes=2 However, I guess there is something I got wrong since after 15 + 2*15 seconds, the TCP sockets are not closed : Before : tcp 0 0 192.168.10.103:52635 ext.domain.net:1234 ESTABLISHED After 2 minutes : tcp 0 0 192.168.10.103:52635 192.168.0.12:1234 ESTABLISHED Did you meant source hacking ? Before hacking into the code, I’d like to make sure my understanding of the keepalive is correct.
Thanks Pete. I added the following, but this didn’t chang the outcome : if ((sock=socket(PF_INET,SOCK_STREAM,0))==-1) return -1; if (setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE, (char*)&option,sizeof (option))==-1) < close(sock) ; return -1; >
Hmm, I expected this to work. The variable option is of type int and has a value of 1? See e.g. tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
This is rarely needed and is often wouldn’t work. TCP is a data transfer protocol, unless there is data loss, nothing should be done. Think twice why you ever would need that.
Otherwise, you can try to periodically poll interface(s) and check for the UP flag. If interface looses UP flag, then OS already reacted on cable being unplugged and down’ed the interface. man 7 netdevice , see SIOCGIFFLAGS for more.
Network drivers also generate an event on even when cable is plugged, but I’m not sure whether you can access that or not from a user. You might want to check the udev as its documentation explicitly mentions network interfaces.
Как закрыть TCP подключение
TCP протокол используется для доступа к SSH серверу, доступа к веб-сайтам и во многих других случаях.
TCP протокол устанавливает подключение для инициализации которого выполняется трёхэтапное рукопожатие, в процессе использования этого подключения происходит контроль целостности передачи данных и повторная передача повреждённых или неполученных пакетов.
В целях контроля нагрузки на сеть, либо для симуляции или выполнения сетевых атак может понадобиться принудительно отключить установленное сетевое подключение.
В этой заметке будет рассказано о нескольких инструментах, с помощью которых вы можете принудительно закрыть TCP подключение.
Как разорвать TCP подключение используя утилиту tcpkill
Tcpkill — это сетевая служебная программа, которая может использоваться для уничтожения соединений с определенным хостом, сетью, портом или их комбинацией. Программа tcpkill входит в пакет dsniff.
sudo tcpkill -i ИНТЕРФЕЙС -9 port ПОРТ sudo tcpkill -i ИНТЕРФЕЙС -9 host IP_ИЛИ_ДОМЕН
Например, я хочу отключить SSH подключение (22й порт) на интерфейсе wlo1:
sudo tcpkill -i wlo1 -9 port 22
Фильтры для подключений могут комбинироваться — вы можете использовать любые варианты Фильтров tcpdump и pcap, больше примеров смотрите в Руководстве по tcpdump.
Принцип работы tcpkill основан на том, что она анализирует передаваемый tcp трафик, вычисляет правильное значение пакета в последовательности и отправляет пакеты для сброса соединения. То есть эта программа может работать только для активных соединений, которые обмениваются трафиком после запуска tcpkill.
Как оборвать TCP соединение с помощью killcx
Killcx — это скрипт на Perl для закрытия TCP подключений в Linux независимо от их состояния (полуоткрытые, установоленные, ожидающие или закрывающиеся).
Killcx работает по следующему принципу: программа создаёт фальшивый SYN пакет с фиктивным номером в последовательности, спуфит удалённый IP/порт клиента и отправляет его на сервер. Это приведёт к ответвлению дочернего процесса, который будет захватывать ответ сервера, извлечёт 2 магических значения из пакета ACK и будет использовать их для отправки спуфленного (поддельного) пакета RST. Затем подключение будет закрыто.
Обратите внимание, что SYN отправляется для того, что если по каким-либо причинам подключение застряло (нет входящих/исхоодящих пакетов), killcx всё равно сможет закрыть его.
Как установить Killcx
Начните с установки зависимостей.
Установка зависимостей Killcx в Debian, Linux Mint, Ubuntu, Kali Linux и их производные:
sudo apt install libnet-rawip-perl libnet-pcap-perl libnetpacket-perl
Установка зависимостей Killcx в Arch Linux, BlackArch и их производные:
sudo pacman -S perl-net-rawip perl-net-pcap perl-netpacket
Далее во всех системах одинаково:
wget -O killcx-1.0.3.tgz https://sourceforge.net/projects/killcx/files/killcx/1.0.3/killcx-1.0.3.tgz/download tar xvzf killcx-1.0.3.tgz sudo mv killcx-1.0.3/killcx /usr/bin/killcx rm -rf killcx-1.0.3* killcx
destip : IP удалённого хоста destport : порт удалённого хоста ИНТЕРФЕЙС (опционально) : сетевой интерфейс (eth0, lo etc). Помните, что во многих случаях использование 'lo' (loopback) даст лучшие результаты, особенно когда подключение ещё не, или уже не в состоянии ESTABLISHED (SYN_RECV, TIME_WAIT и т.д.).
killcx 10.11.12.13:1234 killcx 10.11.12.13:1234 eth0