Убить tcp соединение в linux

49

У меня есть какое-то мертвое соединение в одном приложении, которое находится в зависшем состоянии, если клиентская машина мертва.

->192.168.1.214:49029 (ESTABLISHED)

Есть ли способ прекратить эти опции из командной строки Linux без перезагрузки сервера?

После поиска я нашел решение под названием tcpkill. Но это не сработает для меня. Так как он постоянно блокирует этот ip.

Вивек Гоэль
источник
Ответ на использование ssкоманды гораздо проще и более общий, чем другие.
nealmcb

Ответы:

35

Первоначально из: http://rtomaszewski.blogspot.sk/2012/11/how-to-forcbly-kill-established-tcp.html

Чтобы «убить» сокет, вы должны отправить пакет сброса TCP. Чтобы отправить его (и принять другую сторону), вы должны знать фактический порядковый номер TCP.

1) Уже упомянутый tcpkillметод изучает номер SEQ путем пассивного прослушивания в сети и ожидания получения действительных пакетов этого соединения. Затем он использует полученный номер SEQ для отправки пакетов RSET обеим сторонам. Однако, если соединение неактивно / зависло и данные не передаются, оно ничего не будет делать и будет ждать вечно.

2) Другой метод использует скрипт perl, который называется killcx( ссылка на Sourceforge ). Это активно отправляет поддельные пакеты SYN и узнает номер SEQ из ответа. Затем он отправляет пакеты RSET так же, как tcpkill.

Альтернативный подход (основанный на том, чего вы хотите добиться) - использовать gdbотладчик для подключения к процессу, владеющему этим сокетом / соединением, и close()выполнять системный вызов от его имени - как подробно описано в этом ответе .

Если вы хотите работать только с зависшими соединениями (другая сторона не работает), существуют различные таймауты (например, TCP keepalive), которые должны автоматически закрывать такие соединения, если в системе правильно настроены.

Marki555
источник
Будет ли это работать, если мы просто закроем сокет TCP его файловым дескриптором (fd)? exec fd> & -
Александр Гончий
@AlexanderGonchiy для активных соединений, это предотвратит процесс, чтобы ответить на пакеты, поэтому это приведет к тайм-ауту соединения. Для незанятых соединений ничего бы не случилось. Я не уверен, что ядро ​​отправит что-нибудь в сеть при закрытии fd.
Marki555
Я понюхал порядковый номер. Что мне тогда делать?
user3132194
18

tcpkillможет сделать это для вас. В Ubuntu это в dsniffпакете.

Что-то вроде:

$ sudo tcpkill -i wlan0 host 192.168.1.214

(или какое-либо другое tcpdumpподобное выражение для того, какое соединение убить).

JCV
источник
4
Это работает, только если соединение что-то передает. Это не будет работать для зависших / неактивных TCP-соединений (подробности см. В моем ответе)
Marki555
17

В ядре Linux> = 4.9 вы можете использовать ssкоманду из iproute2 с ключом-K

ss -K dst 192.168.1.214 dport = 49029

ядро должно быть скомпилировано с CONFIG_INET_DIAG_DESTROYвключенной опцией.

Павел
источник
1
Для Linux это действительно лучший способ, и практически единственный, если у вас есть свободные соединения ( tcpkillне может работать). Тем не менее, я признаю, что я не проверял, killcxно кажется, что многие защитные программы не позволят этому работать, если вы не измените свои iptables, чтобы пропустить эти поддельные пакеты.
Сет Робертсон
Спасибо! Работал как шарм sudo ss -K ....на Ubuntu Bionic 18.04 LTS. У меня был tmuxпроцесс, который завис на экране небольшого размера из-за удаленного, но неработающего, но не по тайм-ауту соединения. Все исправлено!
nealmcb
6

Делай - как root netstat -tunp|grep 49029. В последнем столбце выходных данных должны быть указаны PID и имя программы процесса, ответственного за это соединение.

Если вам повезет, есть только один процесс для этого соединения.

Если вам не повезло, все усложняется (PID отвечает не только за одно соединение). Что это за услуга?

Почему вы хотите прекратить эту сессию?

Nils
источник
8
Я не могу убить этот процесс. Это шестеренный сервер. Я хочу просто закрыть соединение.
Вивек Гоэль
0

tcpkillне может закрыть мертвое (зависшее) соединение. Основано libpcap, это конструирует пакет к отправленному FINпакету. Если соединение уже разорвано, оно не может получить правильный порядковый номер.

Единственный способ - закрыть процесс, так что делает везде - НЕ БЕЗОПАСНО.

alswl
источник