Привет, лор.
Всегда удивлялся и немного завидовал людям, которые овладели искусством шейпинга трафика в линуксе. Там начиная от терминологии и заканчивая результатами сплошные заклинания и загадки для непосвященных. И еще удивлялся, почему никто не напишет простой шейпер для тупых вроде меня альтернативно одаренных, которые ниасилевают. Удивлялся-удивлялся, никто так и не писал, и решил делать сам.
Получилась вот такая штука https://github.com/vmxdev/damper/
Работает штука приблизительно так:
При старте создаются два потока. В первом NFQUEUE захватывает пакеты, они анализируются, каждому пакету назначается «вес» (или приоритет) и пакет сохраняется в очереди с приоритетами. NFQUEUE выносит вердикт DROP, т.е. пакет дальше не идет. Когда очередь заполнена, пакеты с низким приоритетом затираются высокоприоритетными. Другой поток выбирает пакеты с наибольшим весом и посылает (точнее, перепосылает) их. Перепосылание происходит с ограниченной скоростью, из-за этого собственно и получается шейпирование.
Вес назначается в «модулях», их искаропки 4 штуки. Можно использовать их вместе, можно по отдельности. Веса пакетов, измеренные в каждом модуле, умножаются на коэффициент(каждому модулю можно задать свой) и складываются. Получается результирующий вес
Модули:
- inhibit_big_flows - подавляет большие потоки. Чем больше передано байт между двумя IP-адресами, тем меньшим становится «вес» пакета. То есть повышается вероятность того что пакет из большой тяжелой сессии будет отброшен. Информация хранится в кольцевом буфере, так что время от времени наступает амнистия (количество отслеживаемых сессий задается в конфиге), потоки замещаются более свежими
- bymark - вес пакетов задается по марке. iptables-ом выставляется марка по каким-то критериям, для этих пакетов будет применяться коэффициент, указанный в конфиге
- entropy - вес считается в зависимости от энтропии (Шенноновской) потока. Поток идентифицируется адресами и номером протокола. Для TCP/UDP учитывается еще и порт источника и назначения. Чем выше энтропия, тем меньше вес. Т.е. шифрованный, сжатый, мультимедиа-трафик отбрасывается с большей вероятностью чем остальной
- и очень примитивный модуль random - просто добавляет случайности в процесс отброса и переупорядочивания пакетов (если использовать только этот модуль, получится классический RED)
Шейпить можно любые направления, хоть входящие, хоть исходящие, все что сможет захватить NFQUEUE и потом корректно обработается сетевым стеком при ре-инъекции в сырой сокет.
Еще шейпер умеет вести примитивную статистику и рисовать графики. Выглядит это так: http://damper.xenoeye.com . Зеленое - сколько пропущено октетов/пакетов, красное - сколько отброшено. График можно позумить/поскроллить.
На больших скоростях и большом количестве пользователей я этот шейпер не тестировал, скорее всего вылезут какие-то неожиданные проблемы. Но на 10-100М и с полутора пользователями выглядит вроде норм. Хотя грузит CPU, но это от корявости кода, можно отпимизировать и оптимизировать.
Если у кого-то есть мысли по поводу, было бы интересно почитать. Экспертов тоже интересно.
Кастну на всякий случай vel, он вроде писал что еще не видел шейперов на NFQUEUE. Вот, как минимум один уже есть