Ограничить пропускную способность на определенном порту в CentOS 7?

Этот ответ основан на принятом ответе наhttps://stackoverflow.com/questions/10683349/forcing-bash-to-expand-variables-in-a-string-loaded-from-a-file

и адаптирован из него.

#!/bin/bash
export FOOBAR="SUCCESS"
file="testfile.txt"
var_name="TEST"
name="$file"

content="$(envsubst < "$file")"
echo "$content"

В отличие от eval, envsubstзаменяет только переменные, нет риска выполнения других программ посредством подстановки команд или чего-то подобного. Это очень простой инструмент для создания шаблонов для оболочки.

envsubstявляется частью утилиты интернационализации GNU gettext (в Debian, она находится в пакете gettext-base).

Обратите внимание, что envsubst(, являясь внешней командой, а не оболочкой, созданной -в ), может видеть только те переменные, которые были экспортированы (, но см. стандартную allexportопцию sh, чтобы сделать оболочку экспортировать впоследствии определенные переменные в среду ).

2
04.10.2019, 07:50
1 ответ

Трафик можно ограничить, используя только Управление трафиком в Linux .

Просто для уточнения, shadowsocks создает туннель с одной стороны в качестве прокси-сервера SOCKS5 (sslocal, я предполагаю, что это то, что работает на сервере OP с учетом заданных портов ), связываясь с удаленная конечная точка (ssserver), которая сама будет связываться с реальными целевыми серверами. shadowsocks обрабатывает SOCKS5 UDP ASSOCIATE и затем использует (SOCKS5 )UDP на том же порту, что и (SOCKS5 )TCP-порт.

Это решение работает как есть(см. примечание 1)как для TCP, так и для UDP, за исключением того, что UDP может создавать дополнительные проблемы :, если источник создает пакеты UDP размера «больше, чем MTU» (, что, вероятно, не должны выполняться хорошо работающим клиентом или сервером ), они фрагментируются. tc , который работает раньше, чем netfilter в входеи позже, чем netfilter в выходе , будет увидеть фрагменты. Порт UDP недоступен фрагментарно, поэтому никакие фильтры их не поймают и ограничения почти не будет. TCP естественным образом использует MTU для ограничения размера пакета (и в любом случае выполняет обнаружение MTU пути ), в большинстве настроек эта проблема не возникает.

Вот ASCII-изображение потока пакетов (полное изображение обычно представляет одно действие клиента, приводящее к двум потокам, один слева и один справа от прокси-сервера):

              traffic controlled      TCP self-adjusting / no UDP control
             ------------->               <-------------
           /                \           /                \
  clients |                  |  proxy  |                  |  remote  ====== real servers
           \                / (sslocal) \                / (ssserver)
             <-------------               ------------->
              traffic controlled       already rate limited

Нет нужды и смысла беспокоиться о трафике с удаленным сервером:

  • исходящие сообщения с прокси-сервера на удаленный сервер, конечно же, будут ограничены входящим потоком клиентов,
  • входящие с удаленных серверов/серверов на прокси
    • TCP обычно настраивается и ведет себя как трафик на стороне клиента.
    • UDP не будет иметь такой возможности, если протокол приложения не может это сделать.Например, :если два видеопотока по простому UDP поступают со стороны сервера и превышают лимит на стороне клиента, оба клиентских потока, скорее всего, будут повреждены. Должна быть обратная связь с приложением, чтобы уменьшить пропускную способность, это выходит за рамки.

В любом случае будет намного сложнее, вероятно, с изменениями внутри shadowsocks, связать боковой трафик удаленного сервера/сервера с клиентским для tc использования.

Для клиентов SOCKS5 требуется только отправка данных, ограничение входящего от них требуется для ограничения пропускной способности, а для клиентов SOCKS5 требуется только получение данных, ограничение исходящего им требуется для ограничения пропускной способности :, если используемое приложение не известно, трафик должен контролироваться в обоих направлениях.

Управление дорожным движением — сложная тема, которую я едва могу коснуться. Я дам два вида ответов :простой и грубый, выполняющий контроль (только отбрасывание излишков ), и более сложный, выполняющий формирование (вкл. задержка перед сбросом )с интерфейсом IFB для обхода ограничений входа .

Приведенную ниже документацию следует прочитать, чтобы понять концепции и реализацию Linux.:

http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/

Кроме того, эта команда, реализованная в сценарии оболочки (и использующая аналогичные механизмы, как в этом ответе ), действительно может творить чудеса:

https://github.com/magnific0/wondershaper

Просто и грубо

Полицейское действие используется для отбрасывания любых избыточных портов сопоставления пакетов (, что является грубым методом ). Обычно он используется для входа , но работает и для выхода . Трафик ограничен по скорости, но могут быть колебания и несправедливое распределение между различными клиентами с ограниченной скоростью (, особенно если речь идет о UDP и TCP ).

  • исходящие(исходящие пакеты)

    Самым простым qdisc , позволяющим прикреплять фильтры, являетсяprioqdisc , особенности которого практически не используются.

    tc qdisc add dev eth0 root handle 1: prio
    

    Простое добавление следующего фильтра (с 8 Мбит/с <=> 1 МБ/с )по одному на порт(u16 at 0 layer transportозначает «исходный порт» ), это будет сделано для TCP и UDP(см. также примечание 2):

    tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081)' action police rate 8mibit burst 256k
    tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
    

    В случае, если я неправильно понял и должен быть только один общий предел для 1081 и 1082, используйте его вместо двух вышеперечисленных, сгруппировав их в одно и то же действие (, что легко с основным / ematch фильтр ), который затем будет обрабатывать их в одном сегменте токенов:

    tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081) or cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
    
  • входящие (входящие пакеты)

    Вход более ограничен, чем выход(не может выполнять формирование ), но в любом случае это не было сделано в простом случае. Для его использования требуется просто добавить ingressqdisc(см. примечание 3):

    tc qdisc add dev eth0 ingress
    

    Эквивалентные фильтры(u16 at 2 layer transportозначают «порт назначения»):

    tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action police rate 8mibit burst 256k
    tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
    

    или для одного лимита вместо двух вышеперечисленных:

    tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081) or cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
    

Очистка tc

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

Чтобы удалить ранее примененные настройки tc, просто удалите root и ingressqdiscs . Все, что ниже их, включая фильтры, также будет удалено. Корневой интерфейс интерфейса по умолчанию qdisc с зарезервированным дескриптором 0 :будет возвращен.

tc qdisc del dev eth0 root
tc qdisc del dev eth0 ingress

Более сложная установка с классовыми дисками qdisc и интерфейсом IFB

Использование формирования , которое может задерживать пакеты перед их отбрасыванием, должно улучшить общие результаты. Ведро маркеров иерархии(HTB ),классовый qdisc будет управлять пропускной способностью, в то время как стохастическая равноправная организация очереди(SFQ)улучшит справедливость между клиентами, когда они конкурируют в пределах ограниченной пропускной способности.

  • выход

    Вот картинка ascii, описывающая следующие настройки:

                        root 1:   HTB classful qdisc
                          |
                        / | \
                       /  |  \
                      /   |   \
                     /    |    \
                    /    1:20  1:30  HTB classes
                   /    8mibit  8mibit
                  /       |       \
                 /        |        \
                /        20:       30:
               /         SFQ       SFQ
         still 1:
         default         port         port
    incl. port 1080      1081         1082
    

    Ограниченная пропускная способность не будет занимать дополнительный доступный трафик (OP не задавала этот вопрос ):, поэтому они не являются подклассом класса по умолчанию «всей доступной пропускной способности». Остальной трафик по умолчанию, включая порт 1080, просто остается на 1 :без специальной обработки. В других условиях, когда классам разрешено заимствовать доступную пропускную способность, эти классы должны быть помещены ниже родительского класса, скорость которого установлена ​​с точным значением максимально доступной пропускной способности, чтобы знать, что заимствовать. Таким образом, конфигурация потребует тонкой -настройки для каждого случая. Я сделал это просто.

    Классовый qdisc htb:

    tc qdisc add dev eth0 root handle 1: htb
    

    Классы htb, прикрепленные sfq и направляющие к ним фильтры:

    tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit
    tc class add dev eth0 parent 1: classid 1:30 htb rate 8mibit
    
    tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
    tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
    
    tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20
    tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:30
    

    или для одного лимита вместо 6 команд выше:

    tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit
    tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
    tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20
    tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:20
    
  • вход

    Ingress qdisc нельзя использовать для формирования (, например задержки пакетов ), а только для их отбрасывания фильтрами, как в простом случае. Для лучшего контроля доступен трюк :Промежуточный функциональный блок , который выглядит как искусственный исходящий интерфейс, где входящий трафик может быть перенаправляется с фильтрами, но мало взаимодействует с остальной частью сетевого стека. После установки к нему можно применить исходящие функции, даже если некоторые из них не всегда могут быть полезны, учитывая, что реальный контроль над входящим трафиком не находится в руках принимающей системы. Итак, здесь я настраиваю интерфейс ifb0, а затем продублирую вышеприведенные настройки(выхода)на нем,иметь вид -формирования входа, который ведет себя лучше, чем просто контроль.

    Создание ifb0(см. примечание 4)и применение тех же настроек, что и для предыдущего выхода:

    ip link add name ifb0 type ifb 2>/dev/null || :
    ip link set dev ifb0 up
    
    tc qdisc add dev ifb0 root handle 1: htb
    

    Классы и направляющие к ним фильтры:

    tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit
    tc class add dev ifb0 parent 1: classid 1:30 htb rate 8mibit
    
    tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10
    tc qdisc add dev ifb0 parent 1:30 handle 30: sfq perturb 10
    
    tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20
    tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:30
    

    или для одного предела, вместо этого, если 6 команд выше:

    tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit     
    tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10
    tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20
    tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:20
    

    Перенаправление с eth0 входящего на ifb0исходящего выполняется ниже. Для оптимизации перенаправляйте только нужные порты, а не весь трафик. Фактическая фильтрация и формирование в любом случае выполняются выше в ifb0 .

    tc qdisc add dev eth0 ingress
    tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0
    tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0
    

Примечания:

1. Протестировано с использованием нескольких сетевых пространств имен в Debian 10/ядре 5.3. Синтаксис команд также протестирован на контейнере CentOS 7.6/ядре 5.3 (, а не 3.10 ).

2. Вместо этого можно было бы использовать u32 match ip sport 1081 0xffffдля сопоставления исходного порта 1081. Но это не обрабатывало бы наличие параметра IP. u32 match tcp src 1081 0xffffможет с этим справиться, но на самом деле требует комплексного использования трехфильтров u32 , как описано в справочной странице . Так что в конце концов я выбрал basic match.

3. ingressимеет зарезервированный дескриптор ffff:независимо от того, указан он или нет (указанное значение дескриптора игнорируется ), поэтому я бы не стал его указывать. Ссылка на вход по parent ffff:может быть заменена просто ingress, так что я выбрал именно это.

4. При первом создании интерфейса IFB загружается модуль ifb, который по умолчанию автоматически создает интерфейсы ifb0 и ifb1 в исходном пространстве имен, что приводит к ошибка, если запрашивается имя интерфейса ifb0, хотя на самом деле он был создан в результате выполнения команды. В то же время этот интерфейс не отображается в сетевом пространстве имен (, например :контейнер ), если просто загружается модуль, поэтому он все еще нужен там.Таким образом, добавление 2>/dev/null || :решает проблему в обоих случаях. Конечно, я предполагаю, что поддержка IFB действительно доступна.

7
27.01.2020, 22:24

Теги

Похожие вопросы