Написано по следам публикации Большие потоки трафика и управление прерываниями в Linux
В нашей городской сети более 30 тысяч абонентов. Суммарный объем внешних каналов — более 3 гигабит. А советы, данные в упомянутой статье, мы проходили еще несколько лет назад. Таким образом, я хочу шире раскрыть тему и поделиться с читателями своими наработками в рамках затрагиваемого вопроса.
В заметке описываются нюансы настройки/тюнинга маршрутизатора и NAT-сервера под управлением Linux, а также приведены некоторые уточнения по поводу распределения прерываний.
Раскидывание прерываний сетевых карт по разным ядрам — это самое первое, с чем сталкивается сисадмин при возрастании нагрузки на linux-маршрутизатор. В упомянутой статье тема освещена достаточно подробно — поэтому надолго останавливаться на этом вопросе мы не будем.
Хочу только отметить:
В первоначальной статье есть фраза «если сервер работает только маршрутизатором, то тюнинг TCP стека особого значения не имеет». Это утверждение в корне неверно. Конечно, на небольших потоках тюнинг не играет большой роли. Однако, если у вас большая сеть и соответствующая нагрузка — то тюнингом сетевого стека вам придется заняться.
Прежде всего, если по вашей сети «гуляют» гигабиты, то имеет смысл обратить свое внимание на MTU на ваших серверах и коммутаторах. В двух словах, MTU — это объем пакета, который можно передать по сети, не прибегая к его фрагментации. Т.е. сколько информации ваш один маршрутизатор может передать другому без фрагментирования. При значительном увеличении объемов передаваемых по сети данных, гораздо эффективнее передавать пакеты большего объема реже, — чем часто-часто пересылать мелкие пакеты данных.
На коммутационном оборудовании обычно это будет называться jumbo-frame. В частности, для Cisco Catalyst 3750
Заметьте: коммутатор затем надо перезагрузить. Кстати, mtu jumbo касаются только гигабитных линков, — 100-мбит такая команда не затрагивает.
По умолчанию значение стоит 1000. Для гигабитных линков рекомендуется ставить 10000. В двух словах, это размер буфера передачи. Когда буфер наполняется до этого граничного значения, данные передаются в сеть.
Имейте ввиду, что если вы меняете размер MTU на интерфейсе какой-то железки — вы должны сделать то же самое и на интерфейсе её «соседа». Т.е., если вы увеличили MTU до 9000 на интерфейсе linux-роутера, то вы должны включить jumbo-frame на порту коммутатора, в который данный роутер включен. В противном случае сеть работать будет, но очень плохо: пакеты ходить по сети будут «через одного».
В результате всех этих изменений, в сети возрастут «пинги» — но общая пропускная способность заметно возрастет, а нагрузка на активное оборудование снизится.
Операция NAT (Network Address Translation) является одной из самых дорогостоящих (в смысле, ресурсоёмких). Поэтому, если у вас большая сеть, без тюнинга NAT-сервера вам не обойтись.
Для осуществления своей задачи, NAT-серверу необходимо «помнить» обо всех соединениях, которые через него проходят. Будь то «пинг» или чья-то «аська» — все эти сессии NAT-сервер «помнит» и отслеживает у себя в памяти в специальной таблице. Когда сессия закрывается, информация о ней из таблицы удаляется. Размер этой таблицы фиксирован. Именно поэтому если трафика через сервер идет достаточно много, а размера таблицы нехватает, — то NAT-сервер начинает «дропать» пакеты, рвать сессии, интернет начинает работать с жуткими перебоями, а на сам NAT-сервер бывает даже попасть по SSH становится просто невозможно.
Чтобы таких ужасов не происходило, необходимо адекватно увеличивать размер таблицы — в соответствии с проходящим через NAT трафиком:
Настоятельно НЕ рекомендуется ставить такое большое значение, если у вас на NAT-сервере меньше 1 гигабайта оперативной памяти.
Посмотреть текущее значение можно вот так:
Посмотреть, насколько уже заполнена таблица отслеживания соединений, можно вот так:
Пропорционально должная быть увеличена и хэш-таблица, в которой хранятся списки conntrack-записей.
Правило простое: hashsize = nf_conntrack_max / 8
Как вы помниите, NAT-сервер отслеживает только «живые» сессии, которые через него проходят. Когда сессия закрывается — информация о ней удаляется, дабы таблица не переполнялась. Информация о сессиях удаляется так же по тайм-ауту. Т.е., если втечение долгого времени в рамках соединения обмена траифка нет — оно закрывается и информация о нем так же удаляется из памяти NAT-а.
Однако, по умолчанию значения тайм-аутов стоят достаточно большие. Поэтому, при больших потоках трафика даже если вы растянете nf_conntrack_max до предела — вы все равно рискуете быстро столкнуться с переполнением таблицы и разрывами соединений.
Чтобы такого не произошло, необходимо грамотно выставить тайм-ауты отслеживания соединений на NAT-сервере.
Текущие значения можно посмотреть, например, так:
В результате вы увидите что-то подобное:
Это значения тайм-аутов в секундах. Как вы видите, значение net.netfilter.nf_conntrack_generic_timeout равно 600 (10 минут). Т.е. NAT-сервер будет держать в памяти информацию о сессии до тех пор, пока по ней будет «пробегать» хоть что-то хотя бы раз в 10 минут.
На первый взгляд, ничего страшного — но на самом деле это очень и очень много.
Если вы посмотрите на net.netfilter.nf_conntrack_tcp_timeout_established — то вы увидите там значение 432000. Другими словами, простую TCP-сессию ваш NAT-сервер будет отслеживать до тех пор, пока по ней не пробегает какой-нибудь пакетик хотя бы раз в 5 дней(!).
Говоря еще более простым языком, за-DDOS'ить такой NAT-сервер становится проще простого: его NAT-таблица (параметр nf_conntrack_max) переполняется «на ура» простейшим флудом — вследствие чего он будет рвать соединения и в худшем варианте быстро превратится в черную дыру.
Значения тайм-аутов рекомендуется ставить в пределах 30-120 секунд. Этого вполне достаточно для нормальной работы абонентов, и этого вполне хватит для своевременной очистки NAT-таблицы, исключающей её переполнение.
И не забудьте вписать соответствующие изменения в /etc/rc.local и /etc/sysctl.conf
После тюнинга вы получите вполне жизнеспособный и производительный NAT-сервер. Конечно же, это только «базовый» тюнинг — мы не касались, например, тюнинга ядра и т.п. вещей. Однако, в большинстве случаев даже таких простых действий будет достаточно для нормальной работы достаточно большой сети. Как я уже говорил, в нашей сети более 30 тыс. абонентов, трафик которых обрабатывают 4 NAT-сервера.
В следующих выпусках:
В нашей городской сети более 30 тысяч абонентов. Суммарный объем внешних каналов — более 3 гигабит. А советы, данные в упомянутой статье, мы проходили еще несколько лет назад. Таким образом, я хочу шире раскрыть тему и поделиться с читателями своими наработками в рамках затрагиваемого вопроса.
В заметке описываются нюансы настройки/тюнинга маршрутизатора и NAT-сервера под управлением Linux, а также приведены некоторые уточнения по поводу распределения прерываний.
Прерывания
Раскидывание прерываний сетевых карт по разным ядрам — это самое первое, с чем сталкивается сисадмин при возрастании нагрузки на linux-маршрутизатор. В упомянутой статье тема освещена достаточно подробно — поэтому надолго останавливаться на этом вопросе мы не будем.
Хочу только отметить:
- если вы вручную раскидываете прерывания, то вам необходимо остановить сервис irqbalance. Этот сервис предназначен как раз для автоматического регулирования прерываний между ядрами процессоров. Если вы делаете эту работу вручную — сервис лучше остановить;
- не забудьте внести соответствующие правки в «автозагрузку» (например, /etc/rc.local) — т.к. после рестарта сервера все прерывания опять распределятся вкучку на одном ядре;
- после рестарта сервера, сетевые карты могут получить (а скорее всего, именно так и будет) новые номера прерываний. Поэтому в /etc/rc.local лучше не вписывать руками конкретные номера прерываний — а автоматизировать с помощью вспомогательного скрипта распознавание, какая сетевая какое прерывание заняла.
Маршрутизатор
В первоначальной статье есть фраза «если сервер работает только маршрутизатором, то тюнинг TCP стека особого значения не имеет». Это утверждение в корне неверно. Конечно, на небольших потоках тюнинг не играет большой роли. Однако, если у вас большая сеть и соответствующая нагрузка — то тюнингом сетевого стека вам придется заняться.
Прежде всего, если по вашей сети «гуляют» гигабиты, то имеет смысл обратить свое внимание на MTU на ваших серверах и коммутаторах. В двух словах, MTU — это объем пакета, который можно передать по сети, не прибегая к его фрагментации. Т.е. сколько информации ваш один маршрутизатор может передать другому без фрагментирования. При значительном увеличении объемов передаваемых по сети данных, гораздо эффективнее передавать пакеты большего объема реже, — чем часто-часто пересылать мелкие пакеты данных.
Увеличиваем MTU на linux
/sbin/ifconfig eth0 mtu 9000
Увеличиваем MTU на коммутаторах
На коммутационном оборудовании обычно это будет называться jumbo-frame. В частности, для Cisco Catalyst 3750
3750(config)# system mtu jumbo 9000
3750(config)# exit
3750# reload
Заметьте: коммутатор затем надо перезагрузить. Кстати, mtu jumbo касаются только гигабитных линков, — 100-мбит такая команда не затрагивает.
Увеличиваем очередь передачи на linux
/sbin/ifconfig eth0 txqueuelen 10000
По умолчанию значение стоит 1000. Для гигабитных линков рекомендуется ставить 10000. В двух словах, это размер буфера передачи. Когда буфер наполняется до этого граничного значения, данные передаются в сеть.
Имейте ввиду, что если вы меняете размер MTU на интерфейсе какой-то железки — вы должны сделать то же самое и на интерфейсе её «соседа». Т.е., если вы увеличили MTU до 9000 на интерфейсе linux-роутера, то вы должны включить jumbo-frame на порту коммутатора, в который данный роутер включен. В противном случае сеть работать будет, но очень плохо: пакеты ходить по сети будут «через одного».
Итоги
В результате всех этих изменений, в сети возрастут «пинги» — но общая пропускная способность заметно возрастет, а нагрузка на активное оборудование снизится.
Сервер NAT
Операция NAT (Network Address Translation) является одной из самых дорогостоящих (в смысле, ресурсоёмких). Поэтому, если у вас большая сеть, без тюнинга NAT-сервера вам не обойтись.
Увеличение кол-ва отслеживаемых соединений
Для осуществления своей задачи, NAT-серверу необходимо «помнить» обо всех соединениях, которые через него проходят. Будь то «пинг» или чья-то «аська» — все эти сессии NAT-сервер «помнит» и отслеживает у себя в памяти в специальной таблице. Когда сессия закрывается, информация о ней из таблицы удаляется. Размер этой таблицы фиксирован. Именно поэтому если трафика через сервер идет достаточно много, а размера таблицы нехватает, — то NAT-сервер начинает «дропать» пакеты, рвать сессии, интернет начинает работать с жуткими перебоями, а на сам NAT-сервер бывает даже попасть по SSH становится просто невозможно.
Чтобы таких ужасов не происходило, необходимо адекватно увеличивать размер таблицы — в соответствии с проходящим через NAT трафиком:
/sbin/sysctl -w net.netfilter.nf_conntrack_max=524288
Настоятельно НЕ рекомендуется ставить такое большое значение, если у вас на NAT-сервере меньше 1 гигабайта оперативной памяти.
Посмотреть текущее значение можно вот так:
/sbin/sysctl net.netfilter.nf_conntrack_max
Посмотреть, насколько уже заполнена таблица отслеживания соединений, можно вот так:
/sbin/sysctl net.netfilter.nf_conntrack_count
Увеличение размера hash-таблицы
Пропорционально должная быть увеличена и хэш-таблица, в которой хранятся списки conntrack-записей.
echo 65536 > /sys/module/nf_conntrack/parameters/hashsize
Правило простое: hashsize = nf_conntrack_max / 8
Уменьшение значений time-out
Как вы помниите, NAT-сервер отслеживает только «живые» сессии, которые через него проходят. Когда сессия закрывается — информация о ней удаляется, дабы таблица не переполнялась. Информация о сессиях удаляется так же по тайм-ауту. Т.е., если втечение долгого времени в рамках соединения обмена траифка нет — оно закрывается и информация о нем так же удаляется из памяти NAT-а.
Однако, по умолчанию значения тайм-аутов стоят достаточно большие. Поэтому, при больших потоках трафика даже если вы растянете nf_conntrack_max до предела — вы все равно рискуете быстро столкнуться с переполнением таблицы и разрывами соединений.
Чтобы такого не произошло, необходимо грамотно выставить тайм-ауты отслеживания соединений на NAT-сервере.
Текущие значения можно посмотреть, например, так:
sysctl -a | grep conntrack | grep timeout
В результате вы увидите что-то подобное:
net.netfilter.nf_conntrack_generic_timeout = 600
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 432000
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 180
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_events_retry_timeout = 15
Это значения тайм-аутов в секундах. Как вы видите, значение net.netfilter.nf_conntrack_generic_timeout равно 600 (10 минут). Т.е. NAT-сервер будет держать в памяти информацию о сессии до тех пор, пока по ней будет «пробегать» хоть что-то хотя бы раз в 10 минут.
На первый взгляд, ничего страшного — но на самом деле это очень и очень много.
Если вы посмотрите на net.netfilter.nf_conntrack_tcp_timeout_established — то вы увидите там значение 432000. Другими словами, простую TCP-сессию ваш NAT-сервер будет отслеживать до тех пор, пока по ней не пробегает какой-нибудь пакетик хотя бы раз в 5 дней(!).
Говоря еще более простым языком, за-DDOS'ить такой NAT-сервер становится проще простого: его NAT-таблица (параметр nf_conntrack_max) переполняется «на ура» простейшим флудом — вследствие чего он будет рвать соединения и в худшем варианте быстро превратится в черную дыру.
Значения тайм-аутов рекомендуется ставить в пределах 30-120 секунд. Этого вполне достаточно для нормальной работы абонентов, и этого вполне хватит для своевременной очистки NAT-таблицы, исключающей её переполнение.
И не забудьте вписать соответствующие изменения в /etc/rc.local и /etc/sysctl.conf
Итоги
После тюнинга вы получите вполне жизнеспособный и производительный NAT-сервер. Конечно же, это только «базовый» тюнинг — мы не касались, например, тюнинга ядра и т.п. вещей. Однако, в большинстве случаев даже таких простых действий будет достаточно для нормальной работы достаточно большой сети. Как я уже говорил, в нашей сети более 30 тыс. абонентов, трафик которых обрабатывают 4 NAT-сервера.
В следующих выпусках:
- большие потоки и высокопроизводительный шейпер;
- большие потоки и высокопроизводительный файрвол.