使用指南
- 修改脚本第 13 行的
MIKROTIK_LAN_SUBNETS,填入你的 MikroTik 需要通过 Ubuntu 代理上网的所有内网网段(例如你的 LAN 是 192.168.88.0/24 和 10.10.10.0/24),多个网段用空格隔开即可。
- 运行
./脚本名称.sh restart (如果你之前装过,直接重启) 或 ./脚本名称.sh install(全新安装)。
- MikroTik 端的配置不需要使用 masquerade 伪装,你只需要通过
Mangle 标记特定的内网流量,然后添加一条路由 dst-address=0.0.0.0/0 gateway=10.100.40.2 (指向Ubuntu内网) 即可。
- 现在你可以通过
./脚本名称.sh status 来观察 Ubuntu 上面是否正确添加了 ip route 路由规则。
#!/bin/bash
# ==========================================
# 1. 基础配置参数 (请根据实际情况修改)
# ==========================================
UBUNTU_PUB_IP="11.22.33.44" # Ubuntu的公网固定IP
MIKROTIK_DDNS="yourname.sn.mynetname.net" # 【请修改】MikroTik的DDNS域名
IPSEC_PSK="YourSuperSecretKey" # 【请修改】IPsec的预共享密钥
TUNNEL_UBUNTU_IP="10.100.100.2" # IPIP隧道 Ubuntu端的内网IP
TUNNEL_MIKROTIK_IP="10.100.100.1" # IPIP隧道 MikroTik端的内网IP
# 【新增】MikroTik的内网网段 (无需在ROS做NAT,Ubuntu会代为NAT并配置回程路由)
# 支持多个网段,用空格分隔。例如:"192.168.88.0/24 10.10.10.0/24"
MIKROTIK_LAN_SUBNETS="10.0.0.0/8"
# 自动获取主网卡名称 (用于NAT代理上网)
MAIN_INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n 1)
# ==========================================
# 前置检查
# ==========================================
if [ "$EUID" -ne 0 ]; then
echo "请使用 root 权限运行此脚本 (例如: sudo $0)"
exit 1
fi
if [ -z "$MAIN_INTERFACE" ]; then
echo "错误: 无法获取默认外网网卡!"
exit 1
fi
# ==========================================
# 功能模块
# ==========================================
function do_install() {
echo ">>> [1/5] 更新并安装必要的软件包..."
apt-get update
apt-get install -y strongswan strongswan-pki libcharon-extra-plugins dnsutils iptables
echo ">>> [2/5] 配置 IPsec (strongSwan) 兼容 MikroTik..."
cat > /etc/ipsec.secrets <<EOF
$UBUNTU_PUB_IP %any : PSK "$IPSEC_PSK"
EOF
cat > /etc/ipsec.conf <<EOF
config setup
charondebug="ike 1, knl 1, cfg 0"
uniqueids=no
conn ipip-tunnel
authby=secret
type=transport
keyexchange=ikev1
left=$UBUNTU_PUB_IP
leftprotoport=4
right=%any
rightprotoport=4
ike=aes256-sha256-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1024!
esp=aes256-sha256-modp2048,aes128-sha1-modp1024,aes256-sha1-modp1024,aes128-sha1,aes256-sha1!
auto=add
dpdaction=clear
dpddelay=30s
EOF
echo ">>> [3/5] 配置系统 IPv4 转发..."
sed -i '/net.ipv4.ip_forward/s/^#//g' /etc/sysctl.conf
grep -q "net.ipv4.ip_forward = 1" /etc/sysctl.conf || echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p >/dev/null
echo ">>> [4/5] 生成 带主动唤醒、心跳机制及回程路由 的 DDNS 守护进程..."
cat > /usr/local/bin/ipip-ddns-daemon.sh <<EOF
#!/bin/bash
CURRENT_IP=""
# 确保 NAT 规则存在 (允许隧道IP和MikroTik内网网段通过Ubuntu上网)
SUBNETS="${TUNNEL_MIKROTIK_IP}/32 ${MIKROTIK_LAN_SUBNETS}"
for subnet in $SUBNETS; do
iptables -t nat -C POSTROUTING -s $subnet -o $MAIN_INTERFACE -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -s $subnet -o $MAIN_INTERFACE -j MASQUERADE
done
while true; do
# 解析 DDNS 获取远端动态 IP
NEW_IP=$(dig +short $MIKROTIK_DDNS | grep -E '^[0-9]+.[0-9]+.[0-9]+.[0-9]+$' | tail -n1)
if [ -n "$NEW_IP" ]; then
if [ "$NEW_IP" != "$CURRENT_IP" ]; then
echo "$(date): MikroTik IP 变更为 '$NEW_IP'. 更新隧道..."
# 删除旧隧道
ip link set ipip0 down 2>/dev/null
ip tunnel del ipip0 2>/dev/null
# 建立新隧道
ip tunnel add ipip0 mode ipip local $UBUNTU_PUB_IP remote $NEW_IP
ip link set ipip0 up
ip addr add $TUNNEL_UBUNTU_IP peer $TUNNEL_MIKROTIK_IP dev ipip0
# 【新增】添加 MikroTik 内网网段的回程路由
for subnet in ${MIKROTIK_LAN_SUBNETS}; do
ip route replace $subnet via $TUNNEL_MIKROTIK_IP dev ipip0
echo "$(date): 已添加回程路由: $subnet -> $TUNNEL_MIKROTIK_IP"
done
CURRENT_IP=$NEW_IP
# 重载 IPsec 触发重新协商
ipsec restart >/dev/null 2>&1
# 【主动唤醒】:等待IPsec服务就绪后,强制发送流量唤醒通道
sleep 3
echo "$(date): 正在主动唤醒 IPsec 通道..."
ping -c 3 -W 1 $TUNNEL_MIKROTIK_IP >/dev/null 2>&1
else
# 【心跳保活 Keepalive】:IP没变时,持续发送静默Ping包保持连接活跃
ping -c 1 -W 1 $TUNNEL_MIKROTIK_IP >/dev/null 2>&1
fi
fi
# 缩短循环时间至 15 秒,加快断线重连速度与心跳频率
sleep 15
done
EOF
chmod +x /usr/local/bin/ipip-ddns-daemon.sh
echo ">>> [5/5] 配置 Systemd 服务..."
cat > /etc/systemd/system/ipip-tunnel.service <<EOF
[Unit]
Description=Dynamic IPIP Tunnel Daemon
After=network.target strongswan-starter.service
[Service]
Type=simple
ExecStart=/usr/local/bin/ipip-ddns-daemon.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable ipip-tunnel.service
do_start
echo "======================================"
echo "安装并启动完成!已启用 主动唤醒 与 心跳保活 功能。"
echo "你可以使用 $0 status 查看运行状态。"
echo "======================================"
}
function do_start() {
echo "正在启动 IPsec 和 IPIP 隧道服务..."
ipsec restart >/dev/null 2>&1
systemctl start ipip-tunnel.service
echo "已启动。"
}
function do_stop() {
echo "正在停止 IPIP 隧道服务..."
systemctl stop ipip-tunnel.service
ipsec stop >/dev/null 2>&1
echo "清理网卡接口和 NAT 规则..."
# 删除网卡时,内核会自动清理挂在它上面的静态路由,所以无需手动删路由
ip link set ipip0 down 2>/dev/null
ip tunnel del ipip0 2>/dev/null
# 清理防火墙 NAT 规则
SUBNETS="${TUNNEL_MIKROTIK_IP}/32 ${MIKROTIK_LAN_SUBNETS}"
for subnet in $SUBNETS; do
iptables -t nat -D POSTROUTING -s $subnet -o $MAIN_INTERFACE -j MASQUERADE 2>/dev/null
done
echo "已停止。"
}
function do_restart() {
do_stop
sleep 2
do_start
}
function do_status() {
echo "================ Systemd 守护进程状态 ================"
systemctl status ipip-tunnel.service --no-pager
echo ""
echo "================ IPsec 通道状态 ======================"
ipsec status
echo ""
echo "================ 网卡接口状态 ========================"
ip a show ipip0 2>/dev/null || echo "ipip0 接口未创建"
echo ""
echo "================ 路由表状态 ========================"
ip route | grep ipip0 || echo "暂无指向 ipip0 的路由"
}
function do_uninstall() {
read -p "确定要彻底卸载并清理配置吗?(y/n): " confirm
if [ "$confirm" != "y" ]; then
echo "已取消卸载。"
exit 0
fi
do_stop
echo "正在移除配置和脚本..."
systemctl disable ipip-tunnel.service 2>/dev/null
rm -f /etc/systemd/system/ipip-tunnel.service
rm -f /usr/local/bin/ipip-ddns-daemon.sh
systemctl daemon-reload
rm -f /etc/ipsec.conf
rm -f /etc/ipsec.secrets
echo "卸载完成!如果不再需要 IPsec,可手动运行: apt purge strongswan"
}
# ==========================================
# 命令行参数解析
# ==========================================
case "$1" in
install)
do_install
;;
start)
do_start
;;
stop)
do_stop
;;
restart)
do_restart
;;
status)
do_status
;;
uninstall)
do_uninstall
;;
*)
echo "使用方法: $0 {install|start|stop|restart|status|uninstall}"
echo ""
echo " install - 覆盖配置并安装/启动服务"
echo " start - 启动隧道和守护进程"
echo " stop - 停止隧道、守护进程,并清理网络接口"
echo " restart - 重启服务"
echo " status - 查看服务运行状态、IPsec状态"
echo " uninstall - 彻底停止服务并清理所有的配置文件"
exit 1
;;
esac