From 919124af890fd1bc974805c78795c4122ec6d682 Mon Sep 17 00:00:00 2001 From: arno Date: Mon, 8 Jun 2026 14:59:16 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE(=E5=B7=A5=E5=85=B7):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20DNS=20=E9=85=8D=E7=BD=AE=E4=B8=8E=E9=98=B2?= =?UTF-8?q?=E7=81=AB=E5=A2=99=E8=84=9A=E6=9C=AC=E5=8F=8A=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=9D=83=E9=99=90=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 DNS 全局配置脚本(含 IPv6 禁用、有线网卡静态 IP) - 添加 UFW 防火墙配置脚本(默认拒绝入站、允许出站) - 添加 Claude Code 本地权限与记忆配置 --- .claude/settings.local.json | 15 ++ .claude/tools/dns_setup.sh | 402 ++++++++++++++++++++++++++++++++ .claude/tools/firewall_setup.sh | 55 +++++ 3 files changed, 472 insertions(+) create mode 100644 .claude/settings.local.json create mode 100755 .claude/tools/dns_setup.sh create mode 100755 .claude/tools/firewall_setup.sh diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..93aafd3 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,15 @@ +{ + "permissions": { + "allow": [ + "Bash(*)" + ], + "deny": [ + "mcp__pencil" + ] + }, + "enabledPlugins": {}, + "outputStyle": "default", + "spinnerTipsEnabled": false, + "autoMemoryEnabled": true, + "autoMemoryDirectory": "/data/git/gitea/szis/isos/tech/.claude/memory" +} \ No newline at end of file diff --git a/.claude/tools/dns_setup.sh b/.claude/tools/dns_setup.sh new file mode 100755 index 0000000..056a36f --- /dev/null +++ b/.claude/tools/dns_setup.sh @@ -0,0 +1,402 @@ +#!/usr/bin/env bash +# ============================================================ +# DNS 全局配置脚本(含 IPv6 禁用 + 有线网卡静态 IP) +# 功能: +# 1. 全局固定 DNS(深圳电信) +# 2. 全局禁用 IPv6(sysctl + GRUB + NM) +# 3. 有线网卡支持用户输入静态 IP +# 用法: sudo bash dns_setup.sh +# ============================================================ + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +DNS_SERVERS="202.96.128.143 202.96.128.68 202.96.134.133 202.96.128.86 202.96.128.166" +GRUB_FILE="/etc/default/grub" +TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') +NOW_TS=$(date +%Y%m%d%H%M%S) + +echo "========================================" +echo " DNS 全局配置 + IPv6 禁用脚本" +echo "========================================" +echo "" + +# 检查 root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}[错误] 请使用 sudo 运行此脚本${NC}" + exit 1 +fi + +# ────────────────────────────────────────── +# 步骤 1: 配置 systemd-resolved 全局 DNS +# ────────────────────────────────────────── +echo "==> 步骤 1/6: 配置 systemd-resolved 全局 DNS" + +if [[ ! -f /etc/systemd/resolved.conf.bak ]]; then + cp /etc/systemd/resolved.conf /etc/systemd/resolved.conf.bak + echo -e "${GREEN}[备份] /etc/systemd/resolved.conf → resolved.conf.bak${NC}" +fi + +cat > /etc/systemd/resolved.conf < 步骤 2/6: sysctl 全局禁用 IPv6" + +cat > /etc/sysctl.d/99-disable-ipv6.conf </dev/null +echo -e "${GREEN}[完成] IPv6 已全局禁用 (sysctl)${NC}" + +if [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6)" == "1" ]]; then + echo -e "${GREEN}[验证] /proc/sys/net/ipv6/conf/all/disable_ipv6 = 1 ✓${NC}" +fi + +# ────────────────────────────────────────── +# 步骤 3: GRUB 内核参数禁用 IPv6 +# ────────────────────────────────────────── +echo "" +echo "==> 步骤 3/6: GRUB 内核参数禁用 IPv6" + +if grep -q "ipv6.disable=1" "$GRUB_FILE" 2>/dev/null; then + echo "[跳过] GRUB 已包含 ipv6.disable=1" +else + cp "$GRUB_FILE" "${GRUB_FILE}.bak.${NOW_TS}" + sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 ipv6.disable=1"/' "$GRUB_FILE" + sed -i 's/^GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 ipv6.disable=1"/' "$GRUB_FILE" + update-grub &>/dev/null || grub2-mkconfig -o /boot/grub2/grub.cfg &>/dev/null + echo -e "${GREEN}[完成] GRUB 内核参数已添加 ipv6.disable=1${NC}" + echo -e "${YELLOW}[提示] GRUB 修改需重启后生效${NC}" +fi + +# ────────────────────────────────────────── +# 步骤 4: 有线网卡静态 IP 配置(含重复检测与清理) +# ────────────────────────────────────────── +echo "" +echo "==> 步骤 4/6: 有线网卡检测与静态 IP 配置" +echo "" + +# 收集所有有线网卡连接,按接口分组 +declare -A IFACE_CONNS # 接口 -> "uuid|cname|uuid|cname|..." (用换行分隔多个) +while IFS= read -r uuid; do + ctype=$(nmcli -t -f connection.type connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-) + cname=$(nmcli -t -f connection.id connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-) + iface=$(nmcli -t -f connection.interface-name connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-) + if [[ "$ctype" == "802-3-ethernet" ]]; then + if [[ -n "${IFACE_CONNS[$iface]:-}" ]]; then + IFACE_CONNS[$iface]="${IFACE_CONNS[$iface]} +$uuid|$cname" + else + IFACE_CONNS[$iface]="$uuid|$cname" + fi + fi +done < <(nmcli -t -f UUID connection show 2>/dev/null) + +if [[ ${#IFACE_CONNS[@]} -eq 0 ]]; then + echo " 未检测到有线网卡连接,跳过。" +else + NETPLAN_DIR="/etc/netplan" + + for iface in "${!IFACE_CONNS[@]}"; do + # 解析该接口的所有连接 + mapfile -t entries <<< "${IFACE_CONNS[$iface]}" + + if [[ ${#entries[@]} -gt 1 ]]; then + echo "" + echo -e " ${YELLOW}══════════════════════════════════════${NC}" + echo -e " ${YELLOW} 检测到接口 [$iface] 有 ${#entries[@]} 个重复连接${NC}" + echo -e " ${YELLOW}══════════════════════════════════════${NC}" + + # 找出活跃连接(有 IP 的) + active_entry="" + stale_uuids=() + for e in "${entries[@]}"; do + IFS='|' read -r euuid ecname <<< "$e" + eip=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP 'inet \K[\d.]+/[\d]+' | head -1) + estate=$(nmcli -t -f GENERAL.STATE connection show uuid "$euuid" 2>/dev/null | cut -d: -f2-) + + echo "" + echo " [$ecname] UUID: $euuid" + echo " 当前 NM 状态: ${estate:-未知}" + + if [[ -n "$eip" ]]; then + # 检查该连接的 IP 是否匹配接口 IP + conn_ip=$(nmcli -t -f IP4.ADDRESS connection show uuid "$euuid" 2>/dev/null | cut -d: -f2- | head -1 | cut -d'/' -f1 | cut -d' ' -f1) + iface_ip=$(echo "$eip" | cut -d'/' -f1) + if [[ "$conn_ip" == "$iface_ip" ]] || [[ "$estate" == "activated" ]]; then + active_entry="$e" + echo -e " ${GREEN}◎ 活跃(当前使用中)${NC}" + else + stale_uuids+=("$euuid") + echo -e " ${YELLOW}⊙ 残留/非活跃${NC}" + fi + else + stale_uuids+=("$euuid") + echo -e " ${YELLOW}⊙ 无 IP,疑似残留${NC}" + fi + done + + # 若未明确找到活跃连接,保留第一个,其余标记为残留 + if [[ -z "$active_entry" ]]; then + active_entry="${entries[0]}" + stale_uuids=() + for ((i=1; i<${#entries[@]}; i++)); do + IFS='|' read -r suuid scname <<< "${entries[$i]}" + stale_uuids+=("$suuid") + done + fi + + # 清理残留连接 + if [[ ${#stale_uuids[@]} -gt 0 ]]; then + echo "" + echo -e " ${YELLOW}将自动清理 ${#stale_uuids[@]} 个残留连接:${NC}" + for suuid in "${stale_uuids[@]}"; do + sname=$(nmcli -t -f connection.id connection show uuid "$suuid" 2>/dev/null | cut -d: -f2-) + echo " - $sname ($suuid)" + done + + read -r -p " 确认清理?[Y/n] " do_clean + if [[ ! "$do_clean" =~ ^[Nn]$ ]]; then + for suuid in "${stale_uuids[@]}"; do + sname=$(nmcli -t -f connection.id connection show uuid "$suuid" 2>/dev/null | cut -d: -f2-) + nmcli connection delete "$suuid" 2>/dev/null || true + rm -f "${NETPLAN_DIR}/90-NM-${suuid}.yaml" + echo -e " ${GREEN}✓ 已删除: $sname${NC}" + done + else + echo " 已跳过清理。" + fi + fi + + # 更新 entries 为仅保留活跃连接 + entries=("$active_entry") + fi + + # 对每个保留的有线连接,配置静态 IP + for e in "${entries[@]}"; do + IFS='|' read -r uuid cname <<< "$e" + + echo "" + echo "────────────────────────────────────────" + echo " 有线网卡: $cname" + echo " 接口名: $iface" + echo " UUID: $uuid" + echo "" + + # 获取当前 IP 信息 + cur_ip="" + cur_gw="" + if [[ -n "$iface" ]] && ip addr show "$iface" &>/dev/null; then + cur_ip=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP 'inet \K[\d.]+/[\d]+' | head -1) + cur_gw=$(ip -4 route show default dev "$iface" 2>/dev/null | awk '{print $3}' | head -1) + fi + + echo " 当前状态:" + echo " IP 地址: ${cur_ip:-未获取}" + echo " 网关: ${cur_gw:-未获取}" + echo "" + + # 询问用户 + read -r -p " 是否为此网卡设置静态 IP?[y/N] " set_static + if [[ ! "$set_static" =~ ^[Yy]$ ]]; then + echo -e " ${YELLOW}⊙ 跳过静态 IP,仅固定 DNS${NC}" + + cur_method=$(nmcli -t -f ipv4.method connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-) + if [[ "$cur_method" == "link-local" ]]; then + echo -e " ${YELLOW}⊙ method=link-local,切换到 auto 以支持 DNS${NC}" + nmcli connection modify "$uuid" ipv4.method auto + fi + nmcli connection modify "$uuid" ipv4.ignore-auto-dns yes + nmcli connection modify "$uuid" ipv4.dns "${DNS_SERVERS// /,}" + nmcli connection modify "$uuid" ipv6.method disabled + continue + fi + + # 输入静态 IP + while true; do + read -r -p " 请输入静态 IP 地址 (格式: x.x.x.x/yy): " static_ip + if [[ "$static_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then + break + fi + echo -e " ${RED}格式错误,示例: 192.168.1.90/24${NC}" + done + + # 输入网关 + read -r -p " 请输入网关地址 (回车使用检测值 ${cur_gw:-无}): " static_gw + if [[ -z "$static_gw" ]]; then + static_gw="$cur_gw" + fi + if [[ -z "$static_gw" ]]; then + echo -e " ${RED}[错误] 网关不能为空${NC}" + continue + fi + + echo "" + echo " 即将应用以下配置:" + echo " 连接名: $cname" + echo " 接口: $iface" + echo " IP: $static_ip" + echo " 网关: $static_gw" + echo " DNS: $(echo "$DNS_SERVERS" | tr ' ' ',')" + echo " IPv6: 禁用" + echo "" + + read -r -p " 确认应用?[Y/n] " confirm + if [[ "$confirm" =~ ^[Nn]$ ]]; then + echo -e " ${YELLOW}⊙ 已取消${NC}" + continue + fi + + # ── 应用 NM 配置 ── + nmcli connection modify "$uuid" \ + ipv4.method manual \ + ipv4.addresses "$static_ip" \ + ipv4.gateway "$static_gw" \ + ipv4.dns "${DNS_SERVERS// /,}" \ + ipv6.method disabled + + echo -e " ${GREEN}✓ NM 配置已写入${NC}" + + # ── 同步 netplan ── + NETPLAN_FILE="${NETPLAN_DIR}/90-NM-${uuid}.yaml" + + if [[ -d "$NETPLAN_DIR" ]]; then + [[ ! -d "${NETPLAN_DIR}.bak" ]] && cp -r "$NETPLAN_DIR" "${NETPLAN_DIR}.bak" + + cat > "$NETPLAN_FILE" </dev/null; then + echo -e " ${GREEN}✓ netplan 语法检查通过${NC}" + else + echo -e " ${YELLOW}⚠ netplan 语法检查有警告,请手动确认${NC}" + fi + fi + + echo "" + done + done +fi + +# ────────────────────────────────────────── +# 步骤 5: 配置 NetworkManager 其余连接 +# ────────────────────────────────────────── +echo "" +echo "==> 步骤 5/6: 配置其余 NetworkManager 连接 (WiFi 等)" + +for conn in $(nmcli -t -f UUID connection show 2>/dev/null); do + ctype=$(nmcli -t -f connection.type connection show uuid "$conn" 2>/dev/null | cut -d: -f2-) + cname=$(nmcli -t -f connection.id connection show uuid "$conn" 2>/dev/null | cut -d: -f2-) + + # 跳过回环 + if [[ "$ctype" == "loopback" ]]; then + nmcli connection modify "$conn" ipv6.method auto 2>/dev/null || true + echo " $cname → ${YELLOW}⊙ 回环,跳过${NC}" + continue + fi + + # 有线网卡已在步骤 4 处理 + if [[ "$ctype" == "802-3-ethernet" ]]; then + echo " $cname → ${YELLOW}⊙ 有线网卡,已在步骤 4 处理${NC}" + continue + fi + + # WiFi 等:固定 DNS + 禁用 IPv6 + cur_method=$(nmcli -t -f ipv4.method connection show uuid "$conn" 2>/dev/null | cut -d: -f2-) + if [[ "$cur_method" == "link-local" ]]; then + nmcli connection modify "$conn" ipv4.method auto + fi + + nmcli connection modify "$conn" ipv4.ignore-auto-dns yes + nmcli connection modify "$conn" ipv4.dns "${DNS_SERVERS// /,}" + nmcli connection modify "$conn" ipv6.method disabled + + echo " $cname (类型: $ctype) → ${GREEN}✓ DNS 固定 / IPv6 禁用${NC}" +done + +# ────────────────────────────────────────── +# 步骤 6: 重启服务 +# ────────────────────────────────────────── +echo "" +echo "==> 步骤 6/6: 重启服务" + +systemctl restart systemd-resolved +echo -e "${GREEN}[完成] systemd-resolved 已重启${NC}" + +# ────────────────────────────────────────── +# 状态汇总 +# ────────────────────────────────────────── +echo "" +echo "========================================" +echo " 当前状态汇总" +echo "========================================" + +echo "" +echo "--- DNS 状态 ---" +resolvectl status 2>&1 || true + +echo "" +echo "--- IPv6 状态 ---" +echo "sysctl disable_ipv6: $(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || echo 'unknown')" +ip -6 addr show 2>/dev/null | grep "inet6" || echo "(无 IPv6 地址)" + +echo "" +echo "--- DNS 解析验证 ---" +for domain in baidu.com qq.com; do + result=$(resolvectl query "$domain" 2>&1 || true) + echo " $domain → $(echo "$result" | head -3)" +done + +echo "" +echo -e "${GREEN}全部配置完成!${NC}" +echo "" +echo -e "${YELLOW}提示: GRUB 修改需重启后完全生效。${NC}" +echo -e "${YELLOW} DNS / IPv6 变动需重连网络后生效。${NC}" diff --git a/.claude/tools/firewall_setup.sh b/.claude/tools/firewall_setup.sh new file mode 100755 index 0000000..f9e2b72 --- /dev/null +++ b/.claude/tools/firewall_setup.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# ============================================================ +# 防火墙配置脚本 +# 功能: 默认拒绝所有入站连接,启用 UFW 并设置开机自启 +# 用法: sudo bash firewall_setup.sh +# ============================================================ + +set -euo pipefail + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "========================================" +echo " 防火墙配置脚本 (UFW)" +echo "========================================" +echo "" + +# 检查是否以 root 运行 +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}[错误] 请使用 sudo 运行此脚本: sudo bash $0${NC}" + exit 1 +fi + +# 检查 UFW 是否已安装 +if ! command -v ufw &> /dev/null; then + echo -e "${RED}[错误] UFW 未安装,请先安装: apt install ufw${NC}" + exit 1 +fi + +echo "" +echo "==> 步骤 1/3: 设置默认策略 — 拒绝所有入站连接" +sudo ufw default deny incoming +echo -e "${GREEN}[完成] 入站默认策略已设为 deny${NC}" + +echo "" +echo "==> 步骤 2/3: 允许出站连接" +sudo ufw default allow outgoing +echo -e "${GREEN}[完成] 出站默认策略已设为 allow${NC}" + +echo "" +echo "==> 步骤 3/3: 启用 UFW(开机自启)" +sudo ufw --force enable +echo -e "${GREEN}[完成] UFW 已启用并设为开机自启${NC}" + +echo "" +echo "========================================" +echo " 当前防火墙状态" +echo "========================================" +sudo ufw status verbose + +echo "" +echo -e "${GREEN}防火墙配置完成!${NC}"