chore: добавлен скрипт для создания прозрачного прокси из сервера

This commit is contained in:
protokey committed 2026-09-26 13:20:25 +04:00
1 parent 064bb70f32
commit 9bb3a2fc5d
7 files changed
+100 -14

No files matched your search

+59 -6
View File
@@ -1,13 +1,66 @@
#!/bin/sh
# Перенаправляет весь входящий трафик сервера на целевой ресурс.
# Использование: serverus-redirect <target_ip>
# Перенаправляет tcp-порты сервера на те же порты целевого ресурса (прозрачный прокси через nftables).
# Использование: serverus-redirect <target_ip> <port>[,<port>...]
# SSH_PORT - порт ssh этого сервера, его перенаправлять нельзя, иначе доступ к серверу будет потерян.
#
# TODO: заглушка. Заменить на настоящий скрипт перенаправления через фаервол.
# Правила должны переживать перезапуск nftables: базовый конфиг /etc/nftables.conf начинается с flush ruleset.
# Правила лежат в отдельном файле и подключаются из /etc/nftables.conf через include:
# базовый конфиг начинается с flush ruleset, поэтому только так они переживают перезапуск nftables.
# Транзитный трафик (forward) и ip_forward должен разрешить вызывающий плейбук.
set -eu
TARGET_IP="${1:?usage: $0 <target_ip>}"
TARGET_IP="${1:?usage: $0 <target_ip> <port>[,<port>...]}"
PORTS="${2:?usage: $0 <target_ip> <port>[,<port>...]}"
SSH_PORT="${SSH_PORT:?SSH_PORT is required}"
echo "redirect stub: all traffic except tcp/${SSH_PORT} -> ${TARGET_IP}"
RULES=/etc/nftables.d/serverus-redirect.nft
CONF=/etc/nftables.conf
# ip route get заодно проверяет, что это ipv4-адрес и что до него есть маршрут
ROUTE=$(ip -4 route get "$TARGET_IP" 2>/dev/null) || { echo "no route to ${TARGET_IP}" >&2; exit 1; }
case "$ROUTE" in
local\ *) echo "${TARGET_IP} is this server, refusing to redirect to itself" >&2; exit 1 ;;
esac
for port in $(echo "$PORTS" | tr ',' ' '); do
case "$port" in
''|*[!0-9]*) echo "bad port: ${port}" >&2; exit 1 ;;
esac
if [ "$port" -eq "$SSH_PORT" ]; then
echo "refusing to redirect ssh port ${SSH_PORT}" >&2
exit 1
fi
done
mkdir -p "$(dirname "$RULES")"
cat > "$RULES" <<EOF
# Сгенерировано serverus-redirect, не править руками.
table ip serverus_redirect {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
# nat видит только новые соединения: ответы на исходящие соединения самого сервера (apt, dns) не трогаются
fib daddr type local tcp dport { ${PORTS} } dnat to ${TARGET_IP}
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# ответ от цели должен вернуться через этот сервер, иначе клиент получит пакет с чужого адреса
ip daddr ${TARGET_IP} ct status dnat masquerade
}
chain forward {
type filter hook forward priority mangle; policy accept;
# mtu по пути может быть меньше, чем думает клиент
tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu
}
}
EOF
grep -qxF "include \"${RULES}\"" "$CONF" || printf '\ninclude "%s"\n' "$RULES" >> "$CONF"
nft -c -f "$CONF"
systemctl restart nftables
echo "redirect: tcp/{${PORTS}} -> ${TARGET_IP}"
+27 -3
View File
@@ -1,6 +1,6 @@
# extravars: target_ip
# extravars: target_ip, ports
#
# Превращает сервер в прозрачный прокси: весь трафик, кроме ssh, уходит на target_ip.
# Превращает сервер в прозрачный прокси: tcp-порты ports уходят на те же порты target_ip.
- name: Redirect traffic to target
hosts: target
gather_facts: false
@@ -10,12 +10,35 @@
firewall_tcp_ports: [ "{{ ansible_port }}" ]
firewall_forward: true
# sysctl при загрузке применяется раньше nftables: без модулей ключи conntrack и bbr не выставятся
- name: Load forwarding kernel modules on boot
ansible.builtin.copy:
dest: /etc/modules-load.d/serverus-forward.conf
mode: "0644"
content: |
nf_conntrack
tcp_bbr
- name: Load forwarding kernel modules
ansible.builtin.command: modprobe -a nf_conntrack tcp_bbr
changed_when: false
- name: Enable ip forwarding
ansible.builtin.copy:
dest: /etc/sysctl.d/90-serverus-forward.conf
mode: "0644"
content: |
net.ipv4.ip_forward = 1
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.netfilter.nf_conntrack_max = 2000000
net.core.netdev_max_backlog = 250000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_slow_start_after_idle = 0
- name: Apply sysctl
ansible.builtin.command: sysctl --system
@@ -28,6 +51,7 @@
mode: "0755"
- name: Redirect traffic
ansible.builtin.command: "/usr/local/sbin/serverus-redirect {{ target_ip }}"
ansible.builtin.command:
argv: [ /usr/local/sbin/serverus-redirect, "{{ target_ip }}", "{{ ports | join(',') }}" ]
environment:
SSH_PORT: "{{ ansible_port }}"
+2
View File
@@ -25,7 +25,9 @@
state: absent
loop:
- /usr/local/sbin/serverus-redirect
- /etc/nftables.d/serverus-redirect.nft
- /etc/sysctl.d/90-serverus-forward.conf
- /etc/modules-load.d/serverus-forward.conf
- name: Reload sysctl
ansible.builtin.command: sysctl --system