• Новые темы в этом разделе публикуются автоматически при добавлении файла в менеджер ресурсов.
    Ручное создание новых тем невозможно.
Иконка ресурса

Мануал Настройка IPtables

Нет прав для скачивания
  • Автор темы Автор темы tapok
  • Дата начала Дата начала

tapok

Выдающийся
Местный
Старожил I степени
Сообщения
51
Розыгрыши
0
Репутация
68
Реакции
212
Баллы
1 338
tapok добавил(а) новый ресурс:

Настройка IPtables - IPtables

Cкрипт обеспечит хорошую базовую защиту IPtables а именно:
Блокировку невалидных пакетов и TCP флагов
Защиту от IP спуфинга
Лимиты на количество соединений с одного IP
SYNPROXY для защиты от SYN flood атак
Автоматический бан атакующих IP на 5 минут
Whitelist для админских IP


Функционал:
Собирает данные - спрашивает IP порты сервера (Login/Game) сетевой интерфейс
Создает бэкап - сохраняет текущие правила iptables и ipset
Настраивает защиту в двух режимах:
Базовый: фильтрация пакетов через...

Узнать больше об этом ресурсе...
 

Спасибо!
Хотел бы поинтересоваться почему используется так много mangle а не raw?
И кажется что лучше блокировать приватные подсети указав интерфейс на который трафик с них пытается попасть, иначе можно полностью отрезать доступ к серверу, или я ошибаюсь?
 
Хотел бы поинтересоваться почему используется так много mangle а не raw?
В RAW нельзя использовать -m conntrack --ctstate
Нельзя проверять TCP флаги с состоянием соединения
В RAW можно было перенести например некоторые правила
Код:
ptables -t raw -A PREROUTING -s 224.0.0.0/3 -j DROP  # Спуфинг
iptables -t raw -A PREROUTING -s 10.0.0.0/8 -j DROP
Но проверки TCP флагов с conntrack остаются в MANGLE:
Код:
iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
И кажется что лучше блокировать приватные подсети указав интерфейс на который трафик с них пытается попасть, иначе можно полностью отрезать доступ к серверу, или я ошибаюсь?
тут спасибо, обновил скрипт
 
tapok обновил(а) ресурс Настройка IPtables новой записью:

Логика блокировки приватных сетей

Docker контейнеры будут работать
Kubernetes pod сети не заблокируются
VPN туннели не пострадают
Внутренние сервисы останутся доступны

Узнать больше об этом обновлении...
 
tapok обновил(а) ресурс Настройка IPtables новой записью:

Теперь скрипт безопасен при обрыве SSH сессии

При запуске таймера создается файл /tmp/firewall_setup.lock с PID процесса
Таймер проверяет существование этого файла перед откатом
Если скрипт завершился (нормально или аварийно) - файл удаляется
Откат происходит только если:
Время вышло (60 сек)
Не подтверждено (confirmed = False)
Файл-флаг существует (скрипт еще работает)

Узнать больше об этом обновлении...
 
Вот вам способ инициировать шелл команду при логине на сервер.
Суть в том, что можно блокировать все пакеты к 7777 порту (геймсерверу), если логин не пройдён (проверяем наличие IP в gs_whitelist ipset). Так мы снижаем нагрузку при ДДОС, атакующим позволено только атаковать логинсервер, а там мы можем установить более жёсткие ограничения. А если логин находится на другом компе, то таким образом мы можем полностью изолировать ГС с минимальной нагрузкой на IPTables (например используя шел команду
Код:
ssh [email protected] 'sudo ipset -! add gs_whitelist $IP'
для дистанционного добавления ИП в gs_whitelist)

Diff:
Subject: [PATCH] Adding shell script execution on login
===================================================================
diff --git a/dist/config/authserver.properties b/dist/config/authserver.properties
--- a/dist/config/authserver.properties    (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/dist/config/authserver.properties    (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -95,6 +95,31 @@
 
 # Minimum: 1800, or you get banned
 TorRefreshRate = 5400
+
+# Execute a shell script when an account logs in into the loginserver.
+ExecuteShellScriptOnLogin = False
+
+# The shell script to be executed. Can be a .sh script path as well.
+# $IP is replaced with the IP address of the client.
+# $ACCOUNT is replaced with the account name of the user.
+ShellScriptOnLogin = sudo ipset -! add gs_whitelist $IP
+
+# The timeout in milliseconds, for the shell script to execute.
+# If the shell script does not execute in the given time, it will fail.
+ShellScriptOnLoginTimeout = 5000
+
+# Enable if you want to forcibly destroy the shell script after its execution or fail.
+# It is recommended to normally close the process, but if you experience issues with the process not exiting,
+# you can temporarily enable this, while you are working on solving the issue.
+ShellScriptDestroyForcibly = False
+
+# Log shell script output to the console for debugging purposes.
+ShellScriptLogging = False
+
+# If the shell script execution fails (err code different than 0 is received),
+# send "There is a system error. Please log in again later" error and close the client.
+PreventLoginOnShellScriptFail = False
+
Index: src/main/java/org/mmocore/authserver/Config.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/org/mmocore/authserver/Config.java b/src/main/java/org/mmocore/authserver/Config.java
--- a/src/main/java/org/mmocore/authserver/Config.java    (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/src/main/java/org/mmocore/authserver/Config.java    (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -76,6 +76,13 @@
     public static boolean TOR_BANNED;
     public static String TOR_BAN_LIST;
     public static long TOR_REFRESH_RATE;
+   
+    public static boolean EXECUTE_SHELL_SCRIPT_ON_LOGIN;
+    public static String SHELL_SCRIPT_ON_LOGIN;
+    public static long SHELL_SCRIPT_ON_LOGIN_TIMEOUT;
+    public static boolean SHELL_SCRIPT_DESTROY_FORCIBLY;
+    public static boolean SHELL_SCRIPT_LOGGING;
+    public static boolean PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL;
 
     private static ScrambledKeyPair[] _keyPairs;
     private static byte[][] _blowfishKeys;
@@ -261,6 +268,13 @@
         TOR_BANNED = serverSettings.getProperty("TorBanned", false);
         TOR_BAN_LIST = serverSettings.getProperty("TorBanList", "https://www.dan.me.uk/torlist/?exit");
         TOR_REFRESH_RATE = Math.min(1800, serverSettings.getProperty("TorRefreshRate", 1800)) * 1000L; // 1800s minimum
+       
+        EXECUTE_SHELL_SCRIPT_ON_LOGIN = serverSettings.getProperty("ExecuteShellScriptOnLogin", false);
+        SHELL_SCRIPT_ON_LOGIN = serverSettings.getProperty("ShellScriptOnLogin", "sudo ipset -! add gs_whitelist $IP");
+        SHELL_SCRIPT_ON_LOGIN_TIMEOUT = serverSettings.getProperty("ShellScriptOnLoginTimeout", 5000);
+        SHELL_SCRIPT_DESTROY_FORCIBLY = serverSettings.getProperty("ShellScriptDestroyForcibly", false);
+        SHELL_SCRIPT_LOGGING = serverSettings.getProperty("ShellScriptLogging", false);
+        PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL = serverSettings.getProperty("PreventLoginOnShellScriptFail", false);
 
         GAME_SERVER_PING_DELAY = serverSettings.getProperty("GameServerPingDelay", 30) * 1000L;
         GAME_SERVER_PING_RETRY = serverSettings.getProperty("GameServerPingRetry", 4);
Index: src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java b/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java
--- a/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java    (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java    (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -18,7 +18,11 @@
 import org.slf4j.LoggerFactory;
 
 import javax.crypto.Cipher;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.time.LocalDateTime;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Format: b[128]ddddddhc b[128]: the rsa encrypted block with the login an password
@@ -156,6 +160,68 @@
             client.close(LoginFailReason.REASON_ATTEMPTED_RESTRICTED_IP);
             return;
         }
+       
+        if (Config.EXECUTE_SHELL_SCRIPT_ON_LOGIN)
+        {
+            int errCode;
+            try
+            {
+                final Process exec = Runtime.getRuntime().exec(Config.SHELL_SCRIPT_ON_LOGIN.replace("$IP", String.valueOf(client.getIpAddress())).replace("$ACCOUNT", String.valueOf(account.getLogin())));
+                if (!exec.waitFor(Config.SHELL_SCRIPT_ON_LOGIN_TIMEOUT, TimeUnit.MILLISECONDS))
+                {
+                    errCode = -1;
+                }
+               
+                BufferedReader stdInput = null;
+                BufferedReader stdErr = null;
+                if (Config.SHELL_SCRIPT_LOGGING)
+                {
+                    stdInput = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+                    stdErr = new BufferedReader(new InputStreamReader(exec.getErrorStream()));
+                }
+               
+                if (exec.isAlive())
+                {
+                    if (Config.SHELL_SCRIPT_DESTROY_FORCIBLY)
+                    {
+                        exec.destroyForcibly();
+                    }
+                    else
+                    {
+                        exec.destroy();
+                    }
+                }
+               
+                if (Config.SHELL_SCRIPT_LOGGING)
+                {
+                    _log.info("Shell script logging: Started");
+                    if (stdInput != null)
+                    {
+                        stdInput.lines().forEach(line -> _log.info("Shell in: {}", line));
+                        stdInput.close();
+                    }
+                   
+                    if (stdErr != null)
+                    {
+                        stdErr.lines().forEach(line -> _log.info("Shell err: {}", line));
+                        stdErr.close();
+                    }
+                }
+               
+                errCode = exec.exitValue();
+            }
+            catch (NullPointerException | IOException | InterruptedException e)
+            {
+                _log.error("Failed to execute shell script on login for account: " + account + " with client: " + client, e);
+                errCode = -1;
+            }
+           
+            if (Config.PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL && errCode != 0)
+            {
+                client.close(LoginFailReason.REASON_SYSTEM_ERROR);
+                return;
+            }
+        }
 
         for (GameServer gs : GameServerManager.getInstance().getGameServers())
             if (gs.getProtocol() >= 2 && gs.isAuthed())
 
Также, мы можем блокировать все длинные пакеты к 2106 (логинсерверу). Он не использует длинные пакеты, а часто при ДДОС атакуют через такие длинные пакеты.

Код:
-A LS -m length --length 250:65535 -m set ! --match-set temp_blacklist src -m comment --comment "Block packets greater than this size as LS doesn\'t work with larger packets." -j BLACKLIST_AND_DROP
 
Итак, раз вам интересно.

Надо отметить, что обработка сетевых пакетов является однопоточной. Используется только 1 процессорный поток на сетевой канал.
От получения пакета, до его обработки в IPTables, всё в одном потоке. Новые пакеты ждут пока поток не завершит всю обработку предыдущего пакета.
Из-за этого, чем больше правил в IPTables (точнее, чем они тежелее), тем меньше пакет можно принимать.
Сетевых каналов не так много (часто 1-4, в зависимости от сетевых интерфейсах). Так что, нет значения, что у вас 32 процессорных потока, почти все они не будут использоваться.
Это значит, что вся сетевая нагрузка будет сконцентрирована в этих потоках (можно поискать какие потоки используются для обработки сети через команду "cat /proc/interrupts")
Я долго искал решение этой проблемы, потому что мои ВПС машины использовали только один поток и при ддос остальные потоки ничего не делали. Наконец-то нашёл штуковину под названием RPS.

RPS Configuration (управление получаемых пакетов)

RPS позволяет перераспределить обработку сетевых пакетов между доступными процессорами,
увеличивая пропускную способность и снижая нагрузку на один CPU.
Это достигается путем привязки конкретного IRQ (прерывания) к определенному ядру процессора.
За счет этого удается более эффективно использовать ресурсы системы и распределить нагрузку равномерно.


Опция находится на:
Bash:
/sys/class/net/<interface>/queues/rx-<n>/rps_cpus

Например, если ваш сетевой интерфейс называется "ens3" и поддерживает 2 канала:
Bash:
/sys/class/net/ens3/queues/rx-0/rps_cpus
/sys/class/net/ens3/queues/rx-1/rps_cpus

Проверьте текущее значение (если отключено, то будет "0"):
Bash:
cat /sys/class/net/ens3/queues/rx-0/rps_cpus

Как включить? (нужен root доступ):
2-поточный процессор:
Bash:
echo "3" > /sys/class/net/ens3/queues/rx-0/rps_cpus
4-поточный процессор:
Bash:
echo "f" > /sys/class/net/ens3/queues/rx-0/rps_cpus
8-поточный процессор:
Bash:
echo "ff" > /sys/class/net/ens3/queues/rx-0/rps_cpus
16-поточный процессор:
Bash:
echo "ffff" > /sys/class/net/ens3/queues/rx-0/rps_cpus
16-поточный процессор:
Bash:
echo "ffffffff" > /sys/class/net/ens3/queues/rx-0/rps_cpus

Короче, это шестнадцатеричное значение битового набора, каждый бит - вкл./выкл. соответствующий поток.
Код:
"1" -> "1", "11" -> "3", "1111" -> "F", "11111111" -> "FF", "01" -> "2", "0111" -> "E"

Если у вас есть более 1 сетевого канала, то сделайте то же самое и для остальных.
Если не хотите включать какой-то процессорный поток в обработку пакетов, то пересчитайте значение битового набора
и поставьте его шестнадцатеричное значение.
 
Назад
Сверху Снизу