Кто-нибудь может обяъянить, почему после подключения к серверу и последующего отключения от него socklist (Linux) еще некоторое время показывает "мертвый" сокет? Если интенсивно подключаться к серверу и отключаться от него, число таких "сокетов-зомби" растет. Может ли это привести к Deny Of Service? (новые сокеты создаются accept()-ом, close() по окончанию работы с новым сокетом вызываю)
Здравствуйте, Linuxoid, Вы писали:
L>Кто-нибудь может обяъянить, почему после подключения к серверу и последующего отключения от него socklist (Linux) еще некоторое время показывает "мертвый" сокет? Если интенсивно подключаться к серверу и отключаться от него, число таких "сокетов-зомби" растет. Может ли это привести к Deny Of Service? (новые сокеты создаются accept()-ом, close() по окончанию работы с новым сокетом вызываю)
После закрытия соединения сокет переходит в состояние TIMED_WAIT2 и находится в нем 75 — 300 секунд (в зависимости от настроек ОС, а вообще не меньше чем 2*ВРЕМЯ ЖИЗНИ ПАКЕТА В СЕТИ). Это сделано для того, чтобы пакеты из предыдущего соединения, затерявшиеся в сети не попали в новое. Более подробно об этом можно прочитать в книжке Стивенса "Unix Network Programming".
Здравствуйте, jedi, Вы писали:
J>После закрытия соединения сокет переходит в состояние TIMED_WAIT2 и находится в нем 75 — 300 секунд.
А это может привести к DOS? (например если за 300 секунд успеет наплодиться 65000 сокетов, или сколько их там может быть по максимуму)
Можно как-то убрать эти 300 секунд?
Здравствуйте, Linuxoid, Вы писали:
L>А это может привести к DOS? (например если за 300 секунд успеет наплодиться 65000 сокетов, или сколько их там может быть по максимуму)
Конечно, и приводит (при хакерских атаках).
L>Можно как-то убрать эти 300 секунд?
Убрать наверно можно как-то административным путем (в зависимости от ОС).
Но надо ли ? Наверное так не зря сделано, иначе будешь какую-то фигню в новом сокете получать
при плохой связи.
Здравствуйте, Linuxoid, Вы писали:
J>>После закрытия соединения сокет переходит в состояние TIMED_WAIT2 и находится в нем 75 — 300 секунд. L>Можно как-то убрать эти 300 секунд?
Кажется можно, но не уверен. Смотреть в сторону setsockopt(SO_LINGER)
Здравствуйте, Linuxoid, Вы писали:
L>Кто-нибудь может обяъянить, почему после подключения к серверу и последующего отключения от него socklist (Linux) еще некоторое время показывает "мертвый" сокет? Если интенсивно подключаться к серверу и отключаться от него, число таких "сокетов-зомби" растет. Может ли это привести к Deny Of Service? (новые сокеты создаются accept()-ом, close() по окончанию работы с новым сокетом вызываю)
Вот диаграмма fsm для TCP.
+---------+ ---------\ active OPEN
| CLOSED | \ -----------
+---------+<---------\ \ create TCB
| ^ \ \ snd SYN
passive OPEN | | CLOSE \ \
------------ | | ---------- \ \
create TCB | | delete TCB \ \
V | \ \
+---------+ CLOSE | \
| LISTEN | ---------- | |
+---------+ delete TCB | |
rcv SYN | | SEND | |
----------- | | ------- | V
+---------+ snd SYN,ACK / \ snd SYN +---------+
| |<----------------- ------------------>| |
| SYN | rcv SYN | SYN |
| RCVD |<-----------------------------------------------| SENT |
| | snd ACK | |
| |------------------ -------------------| |
+---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+
| -------------- | | -----------
| x | | snd ACK
| V V
| CLOSE +---------+
| ------- | ESTAB |
| snd FIN +---------+
| CLOSE | | rcv FIN
V ------- | | -------
+---------+ snd FIN / \ snd ACK +---------+
| FIN |<----------------- ------------------>| CLOSE |
| WAIT-1 |------------------ | WAIT |
+---------+ rcv FIN \ +---------+
| rcv ACK of FIN ------- | CLOSE |
| -------------- snd ACK | ------- |
V x V snd FIN V
+---------+ +---------+ +---------+
|FINWAIT-2| | CLOSING | | LAST-ACK|
+---------+ +---------+ +---------+
| rcv ACK of FIN | rcv ACK of FIN |
| rcv FIN -------------- | Timeout=2MSL -------------- |
| ------- x V ------------ x V
\ snd ACK +---------+delete TCB +---------+
------------------------>|TIME WAIT|------------------>| CLOSED |
+---------+ +---------+
TCP Connection State Diagram
Как видно TIME_WAIT возникает на закрывающей стороне. Т.е.
в Вашем случае Вы вызывая close() переводите fsm в состояние
FIN WAIT-1. После этого fsm обязательно перейдет в TIME WAIT и будет
в нем висеть 2MSL (4 минуты). А в случае, если соединение закрыл клиент
(rcv FIN) такого не возникает. (RFC-793 Section 3.5 хотя ИМХО надуманно,
но таков стандарт).
При этом некторые реализации позволяют переоткрывать сокет в
TIME_WAIT при условии, что seq будет больше, чем любое из предыдущего
соединения.
Здравствуйте, Linuxoid, Вы писали:
L>Здравствуйте, jedi, Вы писали:
J>>После закрытия соединения сокет переходит в состояние TIMED_WAIT2 и находится в нем 75 — 300 секунд.
L>А это может привести к DOS? (например если за 300 секунд успеет наплодиться 65000 сокетов, или сколько их там может быть по максимуму) L>Можно как-то убрать эти 300 секунд?
Убрать конечно можно, но делать этого не в коем слечае нельзя!
а чтоб это немешало тебе открывать новые соединения есть такая опция SO_REUSEADDR
правда еще есть ситуёвина, что закончатся все доступные хенжлы, вроде в линуксах их не шибко много на процесс, но тут уж ничаго не поделаеш, можеш считать кол-во соединений и посылать клиентам что-нить типа попробуй позже
Здравствуйте, Александр, Вы писали:
А>Здравствуйте, Linuxoid, Вы писали:
L>>Здравствуйте, jedi, Вы писали:
J>>>После закрытия соединения сокет переходит в состояние TIMED_WAIT2 и находится в нем 75 — 300 секунд.
L>>А это может привести к DOS? (например если за 300 секунд успеет наплодиться 65000 сокетов, или сколько их там может быть по максимуму) L>>Можно как-то убрать эти 300 секунд? А>Убрать конечно можно, но делать этого не в коем слечае нельзя! А>а чтоб это немешало тебе открывать новые соединения есть такая опция SO_REUSEADDR А>правда еще есть ситуёвина, что закончатся все доступные хенжлы, вроде в линуксах их не шибко много на процесс, но тут уж ничаго не поделаеш, можеш считать кол-во соединений и посылать клиентам что-нить типа попробуй позже
Ну почему-же . Для снятия ограничения на сокеты для select()
1. Надо до включения socket.h (или аналогичный) проставить переменную FD_SETSIZE
2. Использовать poll() или другие механизмы как kevents в FreeBSD или epoll в linux