bugfix
This commit is contained in:
parent
41a086d7ec
commit
9c99d67db3
@ -5,6 +5,7 @@ set -eo pipefail
|
||||
# 网关主机配置变量 - 请根据你的实际环境修改!
|
||||
# ==============================================================================
|
||||
# 网关主机内网IP (用于其他内网主机连接)
|
||||
curuser=$(id -un)
|
||||
GATEWAY_LAN_IP="{{ gateway_lan_ip }}"
|
||||
GATEWAY_LAN_CIDR="{{ gateway_lan_cidr }}" # 内网网段
|
||||
# DHCP 租约范围
|
||||
@ -19,6 +20,7 @@ LAN_INTERFACE="{{ lan_interface }}" # 连接内网的网卡,我们将配置静
|
||||
# SSH SOCKS5 代理配置
|
||||
REMOTE_SSH_USER="{{ remote_ssh_user }}" # 远程服务器的SSH用户名
|
||||
REMOTE_SSH_IP="{{ remote_ssh_ip }}" # 远程服务器的IP地址
|
||||
REMOTE_SSH_NAME="{{ remote_ssh_name }}" # 远程服务器的IP地址
|
||||
REMOTE_SSH_PORT="{{ remote_ssh_port }}" # 远程服务器的SSH端口
|
||||
LOCAL_SOCKS5_PORT="{{ local_socks5_port }}" # SSH SOCKS5 代理在本机监听的端口 (127.0.0.1:1080)
|
||||
|
||||
@ -71,7 +73,7 @@ install_package() {
|
||||
# ==============================================================================
|
||||
# 0. 前置检查与环境初始化
|
||||
# ==============================================================================
|
||||
check_root
|
||||
# check_root
|
||||
log_info "开始网关主机配置脚本..."
|
||||
|
||||
log_info "更新系统软件包列表..."
|
||||
@ -149,11 +151,12 @@ max-lease-time ${DHCP_LEASE_TIME};
|
||||
authoritative;
|
||||
|
||||
# A slightly different configuration for an internal subnet.
|
||||
subnet {{ gateway_lan_cidr%.* }}.0 netmask 255.255.255.0 {
|
||||
{% set net_base = gateway_lan_ip.split('.') | slice(3) | join('.') %}
|
||||
subnet {{ net_base }}.0 netmask 255.255.255.0 {
|
||||
range ${DHCP_START_IP} ${DHCP_END_IP};
|
||||
option routers ${GATEWAY_LAN_IP};
|
||||
option domain-name-servers ${GATEWAY_LAN_IP}; # DNS 指向网关主机本身
|
||||
option broadcast-address {{ gateway_lan_cidr%.* }}.255;
|
||||
option broadcast-address {{ net_base }}.255;
|
||||
default-lease-time ${DHCP_LEASE_TIME};
|
||||
max-lease-time ${DHCP_LEASE_TIME};
|
||||
}
|
||||
@ -186,7 +189,7 @@ User=${curuser}
|
||||
Type=simple
|
||||
# 注意:这里需要确保用户 {{ remote_ssh_user }} 是一个实际存在的用户,并且可以访>问其 $HOME/.ssh
|
||||
# 为了简化,我们暂时用root运行,但更推荐使用非root用户
|
||||
ExecStart=/usr/bin/ssh -D ${LOCAL_SOCKS5_PORT} -N -p ${REMOTE_SSH_PORT} ${REMOTE_SSH_USER}@${REMOTE_SSH_IP} -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3
|
||||
ExecStart=/usr/bin/ssh -D ${LOCAL_SOCKS5_PORT} -N -p ${REMOTE_SSH_PORT} ${REMOTE_SSH_USER}@${REMOTE_SSH_NAME} -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3
|
||||
# 使用 Restart 策略确保连接断开时自动重连
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
@ -308,12 +311,19 @@ log_info "设置 GFW 规则定时更新任务 (每天凌晨 3:00)..."
|
||||
(sudo crontab -l 2>/dev/null; echo "0 3 * * * cd ${GFWLIST2NEW_DIR} && sudo python3 ${LOCAL_SCRIPT_NAME} -p ${SOCKS5_SERVER_ADDR} -f "{{ foreign_dns1 }} {{ foreign_dns2 }}" -d "{{ domestic_dns1 }} {{domestic_dns1}}" && sudo systemctl restart dnsmasq") | sudo crontab -
|
||||
log_info "规则生成器配置完成并设置定时更新。"
|
||||
cd - > /dev/null
|
||||
|
||||
# ==============================================================================
|
||||
# 7. 配置 IPTABLES 规则实现透明代理和 NAT (保持不变)
|
||||
# 7. 配置 IPTABLES 规则实现透明代理和 NAT (修正完整版)
|
||||
# ==============================================================================
|
||||
log_info "配置 IPTABLES 规则 (NAT 和透明代理)..."
|
||||
|
||||
# 变量定义检查(确保这些变量在脚本前面已正确定义)
|
||||
# REMOTE_SSH_IP: 远程SOCKS5服务器的公网IP
|
||||
# WAN_INTERFACE: 外网网卡名,如 eth0
|
||||
# LAN_INTERFACE: 内网网卡名,如 enx...
|
||||
|
||||
# 清除现有规则,避免冲突
|
||||
log_info "清除现有 IPTABLES 规则..."
|
||||
sudo iptables -F
|
||||
sudo iptables -X
|
||||
sudo iptables -t nat -F
|
||||
@ -330,15 +340,44 @@ sudo iptables -A FORWARD -i {{ lan_interface }} -o {{ wan_interface }} -j ACCEPT
|
||||
sudo iptables -A FORWARD -o {{ lan_interface }} -i {{ wan_interface }} -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
log_info "已配置 IP 转发规则。"
|
||||
|
||||
# 3. 透明代理规则 (使用 redsocks 和 ipset)
|
||||
# 重定向到 redsocks 的流量,不处理来自 redsocks 本身的流量
|
||||
sudo iptables -t nat -A PREROUTING -i {{ lan_interface }} -p tcp -s {{ gateway_lan_cidr }} -m set --match-set gfwlist dst -j REDIRECT --to-ports ${REDSOCKS_PORT}
|
||||
log_info "已配置透明代理重定向规则 (所有端口,目标IP在 gfwlist 中的内网TCP流量到 redsocks)。"
|
||||
# 3. 透明代理规则 (核心的 PREROUTING 链)
|
||||
log_info "配置透明代理 PREROUTING 排除和重定向规则..."
|
||||
|
||||
# 排除 redsocks 自身流量循环
|
||||
# 这一步非常重要,避免 redsocks 自己产生流量又被 iptables 捕获
|
||||
sudo iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport ${REDSOCKS_PORT} -j RETURN
|
||||
sudo iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport ${LOCAL_SOCKS5_PORT} -j RETURN
|
||||
# --- 排除规则(必须在重定向规则之前) ---
|
||||
|
||||
# 3.1 排除所有重定向到本地的流量(已经通过 OUTPUT 排除,这里可以再加一层保险)
|
||||
sudo iptables -t nat -A PREROUTING -d 127.0.0.0/8 -j RETURN || log_error "排除本地回环失败。"
|
||||
|
||||
# 3.2 排除局域网内流量 (不代理内网互访)
|
||||
sudo iptables -t nat -A PREROUTING -i {{ lan_interface }} -d {{ gateway_lan_cidr }} -j RETURN || log_error "排除内网流量失败。"
|
||||
|
||||
# 3.3 【❗ 补充:排除远程 SSH 服务器 IP ❗】
|
||||
# 避免 SSH 连接本身被重定向,防止无限循环。
|
||||
# 假设变量 REMOTE_SSH_IP 已经正确替换。
|
||||
sudo iptables -t nat -A PREROUTING -d {{ remote_ssh_ip }} -j RETURN || log_error "排除远程 SSH IP 失败。"
|
||||
log_info "已添加规则:排除远程 SSH 服务器 {{ remote_ssh_ip }}。"
|
||||
|
||||
|
||||
# 3.4 【❗ 补充:排除国内 IP ❗】
|
||||
# 排除目标 IP 在 china_ip 集合中的流量(国内流量直连)
|
||||
# 假设 china_ip 集合通过其他脚本/步骤创建
|
||||
# 注意:您的 gfwlist2new/gfw_rules_generator 脚本只处理 gfwlist,这里不需要 china_ip 的 ipset 排除
|
||||
# 而是依赖 gfwlist ipset 的精准捕获。我们移除这个容易出错的步骤,只依赖 gfwlist。
|
||||
# 如果需要排除国内 IP 段,需要有外部脚本维护 china_ip 集合。
|
||||
|
||||
# --- 重定向规则 ---
|
||||
|
||||
# 3.5 核心重定向规则:
|
||||
# 只有流量目标 IP 在 gfwlist ipset 集合中,才重定向到 redsocks。
|
||||
# 注意:该规则必须在排除规则之后。
|
||||
sudo iptables -t nat -A PREROUTING -i {{ lan_interface }} -p tcp -s {{ gateway_lan_cidr }} -m set --match-set gfwlist dst -j REDIRECT --to-ports ${REDSOCKS_PORT}
|
||||
log_info "已配置透明代理重定向规则 (目标IP在 gfwlist 中的内网TCP流量到 redsocks)。"
|
||||
|
||||
|
||||
# 4. 排除 redsocks 自身流量循环 (OUTPUT 链)
|
||||
# 这一步非常重要,避免 redsocks/ssh 客户端自己产生流量又被 iptables 捕获
|
||||
# 排除目标地址是 127.0.0.1 的流量,它们是 SSH 和 Redsocks 的内部通信。
|
||||
sudo iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp -j RETURN
|
||||
log_info "已配置排除 redsocks 自身流量循环的规则。"
|
||||
|
||||
# 保存 iptables 规则
|
||||
@ -346,9 +385,3 @@ sudo netfilter-persistent save || log_error "保存 iptables 规则失败。"
|
||||
sudo systemctl enable netfilter-persistent || log_error "启用 netfilter-persistent 服务失败。"
|
||||
log_info "IPTABLES 规则已配置并保存。"
|
||||
|
||||
log_info "----------------------------------------------------------------------------------"
|
||||
log_info "网关主机配置完成!"
|
||||
log_info "请检查 redsocks 和 ssh -D 进程是否正常运行。"
|
||||
log_info "请注意:SSH SOCKS5 代理可能需要手动输入密码或配置免密登录才能持久运行。"
|
||||
log_info "内网主机现在应该可以自动通过 DHCP 获取 IP 并访问网络。"
|
||||
log_info "----------------------------------------------------------------------------------"
|
||||
|
||||
@ -10,7 +10,6 @@ GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.
|
||||
def log_info(message):
|
||||
print(f"[INFO] {message}")
|
||||
|
||||
# 注意:foreign_dns_list 和 domestic_dns_list 现在是列表
|
||||
def generate_rules(proxy_server, foreign_dns_list, domestic_dns_list, ipset_name="gfwlist"):
|
||||
"""
|
||||
生成 Dnsmasq 和 IPSet 规则文件。
|
||||
@ -19,10 +18,18 @@ def generate_rules(proxy_server, foreign_dns_list, domestic_dns_list, ipset_name
|
||||
log_info("错误:必须提供至少一个国内 DNS 和一个国外 DNS。")
|
||||
sys.exit(1)
|
||||
|
||||
# --- 代理配置:通过本地 SOCKS5 隧道下载 GFWList ---
|
||||
proxies = {
|
||||
'http': f'socks5h://{proxy_server}', # socks5h 使用远程 DNS 解析
|
||||
'https': f'socks5h://{proxy_server}'
|
||||
}
|
||||
log_info(f"配置代理:使用 {proxy_server} 通过隧道下载 GFWList...")
|
||||
# ----------------------------------------------------
|
||||
|
||||
try:
|
||||
log_info(f"正在从 {GFWLIST_URL} 下载 GFWList...")
|
||||
# 尝试通过代理下载 GFWList (这里假设环境已配置或可以直接访问 GitHub)
|
||||
response = requests.get(GFWLIST_URL, timeout=30)
|
||||
# 传入 proxies 参数,强制 requests 走代理
|
||||
response = requests.get(GFWLIST_URL, timeout=30, proxies=proxies)
|
||||
response.raise_for_status()
|
||||
|
||||
# 1. 解码 GFWList
|
||||
@ -33,7 +40,7 @@ def generate_rules(proxy_server, foreign_dns_list, domestic_dns_list, ipset_name
|
||||
content = response.text
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
log_info(f"下载 GFWList 失败,请检查网络连接: {e}")
|
||||
log_info(f"致命错误:通过代理下载 GFWList 失败,请检查 SSH SOCKS5 隧道状态!: {e}")
|
||||
# 如果下载失败,中止脚本以避免生成空文件
|
||||
sys.exit(1)
|
||||
|
||||
@ -67,13 +74,13 @@ def generate_rules(proxy_server, foreign_dns_list, domestic_dns_list, ipset_name
|
||||
|
||||
try:
|
||||
with open(dnsmasq_conf_path, 'w') as f:
|
||||
f.write(f"# Dnsmasq rules generated by gfw_rules_generator.py on {os.path.basename(__file__)}\n")
|
||||
f.write(f"# Dnsmasq rules generated by {os.path.basename(__file__)} on {os.uname().nodename}\n")
|
||||
|
||||
# 写入所有国内 DNS 服务器
|
||||
for dns in domestic_dns_list:
|
||||
f.write(f"server={dns}\n")
|
||||
|
||||
# GFWList 域名设置 (通过代理的上游 DNS 解析,并加入 IPSet)
|
||||
# GFWList 域名设置
|
||||
for domain in sorted(list(domains)):
|
||||
# 1. 将域名加入 IPSet 集合 (由 dnsmasq 动态处理)
|
||||
f.write(f"ipset=/{domain}/{ipset_name}\n")
|
||||
@ -107,6 +114,9 @@ if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 在开始生成规则之前,必须确保 requests 库已经安装 socks5 支持
|
||||
# 确保在 Bash 脚本中已经执行: sudo pip3 install requests PySocks
|
||||
|
||||
log_info("开始生成 GFWList 规则...")
|
||||
generate_rules(args.proxy, args.foreign_dns, args.domestic_dns, args.name)
|
||||
log_info("规则生成完成。")
|
||||
|
||||
@ -15,10 +15,11 @@ config_vars = {
|
||||
"dhcp_lease_time": "7200",
|
||||
"remote_ssh_user": "kww",
|
||||
"remote_ssh_ip": "8.222.165.87", # !!! 替换为你的远程SSH服务器IP
|
||||
"remote_ssh_name": "atvoe.com", # !!! 替换为你的远程SSH服务器域名
|
||||
"remote_ssh_port": "22",
|
||||
"local_socks5_port": "1080",
|
||||
"redsocks_port": "55555",
|
||||
"domestic_dns1": "223.5.5.5"
|
||||
"domestic_dns1": "223.5.5.5",
|
||||
"domestic_dns2": "114.114.114.114",
|
||||
"foreign_dns1": "8.8.8.8",
|
||||
"foreign_dns2": "1.1.1.1",
|
||||
@ -39,13 +40,5 @@ with open('gateway.sh', 'w') as f:
|
||||
f.write(rendered_gateway_script)
|
||||
print("Generated gateway_config.sh")
|
||||
|
||||
# 4. 渲染 client_config.sh
|
||||
client_template = env.get_template('client_config.sh.j2')
|
||||
rendered_client_script = client_template.render(config_vars) # 客户端脚本也需要一些全局变量
|
||||
|
||||
with open('client_config.sh', 'w') as f:
|
||||
f.write(rendered_client_script)
|
||||
print("Generated client_config.sh")
|
||||
|
||||
print("\n!!! 请务必检查生成的 .sh 文件,特别是 SSH 代理和网卡名称等配置。")
|
||||
print("在执行前,给它们添加可执行权限:chmod +x gateway_config.sh client_config.sh")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user