跳至内容

Jixun's Blog 填坑还是开坑,这是个好问题。

线上配置防火墙辅助脚本

前段时间整了个灵车 - 网站后台没有 VNC,甚至连简单的开关机都没有。

即便如此,防火墙还是要配置的,用来限制端口访问等。

用途 #

因为服务器很灵车,如果防火墙配置有问题造成了不可逆转的错误,则需要一个能自动恢复的机制。

因此,你需要另一台可控的服务器(或类似 pastebin 的服务),通过定期查询最新的指令执行操作。

最简单的方案则是利用 Python 开一个临时服务器:

mkdir -p /tmp/firewall_helper
echo 'clock' > /tmp/firewall_helper/cmd.txt

# 在 ip:8080 提供访问
python3 -m http.server --directory /tmp/firewall_helper 8080

需求:

  • 网络无法联通时自动重启当前服务器;
  • 若出口正常但是入口被阻挡,可以通过读取服务器指令进行自动重启或其它自定义操作;

脚本本体 #

#!/bin/bash

# 如果需要调试就取消注释
# set -x

work() {
  local ERROR_COUNT=0
  local CURL_EXIT=0
  local RESP=""
  local CMD=""
  local PARAM=""
  local CMD_URL="${1:-http://example.com/cmd.txt}"

  echo "Current user: $(whoami)"

  while true; do
    RESP="$(curl -sfL "$CMD_URL")"
    CURL_EXIT="$?"

    printf "resp = %s\n" "$RESP"

    if [[ "$CURL_EXIT" -ne 0 ]]; then
      echo "ERROR: curl error = ${CURL_EXIT}"
      ERROR_COUNT="$((ERROR_COUNT + 1))"
    else
      # 简易命令解析器。
      # 格式为 "指令 参数",参数/指令不能包含空格。
      CMD="$(echo -n "$RESP" | cut -d' ' -f1)"
      PARAM="$(echo -n "$RESP" | cut -d' ' -f2)"
      case "$CMD" in
      reboot) reboot || sudo reboot ;;
      ping) echo pong ;;
      clock) date ;;
      hello) printf "hello: %s\n" "$PARAM" ;;
      *)
        echo "ERROR: unknown command = ${CMD}"
        ERROR_COUNT="$((ERROR_COUNT + 1))"
        ;;
      esac
    fi

    # 连续错误 3 次,可能网络出问题了。
    if [[ "$ERROR_COUNT" -ge 3 ]]; then
      echo 'network error: reboot'
      reboot || sudo reboot
      return
    fi

    echo "Waiting... ERROR_COUNT = ${ERROR_COUNT}"
    sleep 5
  done
}

work "$@" 2>&1 | tee ./network.log

使用方法 #

储存上述的脚本本体代码至 firewall_helper.sh

将其标记为可执行:

chmod a+x ./firewall_helper.sh

然后执行。注意将参数替换为你自己可控的地址:

./firewall_helper.sh "http://example.com:8080/cmd.txt"

另外开启一个 SSH 连接并连接到服务器,确保:

  • 服务器在重启后的状态,能通过 SSH 远程连接。

※ 如果你熟悉 screentmux,也可以在服务器使用他们代替使用多个 SSH 连接。

此时可以在新的 SSH 会话进行线上防火墙规则的调整。

使用 nftables 防火墙规则 #

我使用的是 Debian 服务器上的 nftables 来进行管理。

配置文件是纯文本格式,且可以加入简单的变量来编写一次应用规则,然后在不同的机器上微调变量。

首先随便找个地方定义规则文件,并设置为可执行(chmod a+x rules.nft):

#!/usr/sbin/nft -f

# 确保该文件不会被系统启动时自动加载。
# 测试成功后手动拷贝到能被系统读取的配置处。

# reset
flush ruleset

# ... rules ...

然后就是重复上述的步骤,直到规则配置满意为止。

后记 #

因为灵车程度过高,这个脚本反而占据了我大部分的时间… 防火墙规则编写倒是安安稳稳的,在没有把网络搞炸的情况下调试完成了。

知识共享许可协议 本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

评论区