大致说下物理环境
- 两台服务器,分别都有两个网卡eth0和eth1
- eth0用来接入公网IP,eth1用来两个服务连接走内网专线
- 由于每台机器只有一个公网IP,所以虚拟机必须做NAT转换进行上网
下面是网络配置
auto lo
iface lo inet loopback
iface eth0 inet manual
#外网网口
iface eth1 inet manual
#内网网口
auto vmbr0
iface vmbr0 inet static
address 192.168.0.204/24
gateway 192.168.0.1
bridge-ports eth0
bridge-stp off
bridge-fd 0
#外网入口
auto vmbr1
iface vmbr1 inet static
address 10.0.0.1/24
bridge-ports eth1
bridge-stp off
bridge-fd 0
#内网通信专用
auto vmbr2
iface vmbr2 inet static
address 10.10.10.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o vmbr0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o vmbr0 -j MASQUERADE
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
#NAT网络
需要注意
在启用了防火墙的一些 MASQUERADE 设置中,出站连接可能需要使用 conntrack zones。否则,防火墙可能会阻止出站连接,因为它们会优先选择 VM 桥接的 POSTROUTING 规则(而不是 MASQUERADE 规则)进行处理
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
就因为上面这破玩意导致我一天没解决上网问题
用来保存iptables规则,下次重启也会自动生效
apt install iptables-persistent
netfilter-persistent save
还有个手动添加端口转发的工具,需要新建两个文件,一个iptables.sh
和iptables.conf.sh
,iptables.sh
是用来执行添加端口转发的,iptables.conf.sh
是用来保存内容,以便于后续进行删除和展示已添加的转发内容,可以配合netfilter-persisten save
进行使用
注意:里面的vmbr0接口根据你的实际情况进行修改,比如我的是vmbr0是公网IP绑定的接口,那么需要将公网的端口转发到内网的虚拟机则使用vmbr0
#! /bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#ConfFile
iptablesconf='/root/iptables.config.sh'
function rootness(){
if [[ $EUID -ne 0 ]]; then
echo "脚本需要以ROOT权限运行!"
exit 1
fi
}
function conf_list(){
cat $iptablesconf
}
function conf_add(){
if [ ! -f $iptablesconf ];then
echo "找不到配置文件!"
exit 1
fi
echo "请输入虚拟机的内网IP"
read -p "(Default: Exit):" confvmip
[ -z "$confvmip" ] && exit 1
echo
echo "虚拟机内网IP = $confvmip"
echo
while true
do
echo "请输入虚拟机的端口:"
read -p "(默认端口: 22):" confvmport
[ -z "$confvmport" ] && confvmport="22"
expr $confvmport + 0 &>/dev/null
if [ $? -eq 0 ]; then
if [ $confvmport -ge 1 ] && [ $confvmport -le 65535 ]; then
echo
echo "虚拟机端口 = $confvmport"
echo
break
else
echo "输入错误,端口范围应为1-65535!"
fi
else
echo "输入错误,端口范围应为1-65535!"
fi
done
echo
while true
do
echo "请输入宿主机的端口"
read -p "(默认端口: 10022):" natconfport
[ -z "$natconfport" ] && natconfport="10022"
expr $natconfport + 0 &>/dev/null
if [ $? -eq 0 ]; then
if [ $natconfport -ge 1 ] && [ $natconfport -le 65535 ]; then
echo
echo "宿主机端口 = $natconfport"
echo
break
else
echo "输入错误,端口范围应为1-65535!"
fi
else
echo "输入错误,端口范围应为1-65535!"
fi
done
echo "请输入转发协议:"
read -p "(tcp 或者 udp ,回车默认操作: 退出):" conftype
[ -z "$conftype" ] && exit 1
echo
echo "协议类型 = $conftype"
echo
iptablesshell="iptables -t nat -A PREROUTING -i vmbr0 -p $conftype --dport $natconfport -j DNAT --to-destination $confvmip:$confvmport"
if [ `grep -c "$iptablesshell" $iptablesconf` != '0' ]; then
echo "配置已经存在"
exit 1
fi
get_char(){
SAVEDSTTY=`stty -g`
stty -echo
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
echo
echo "回车继续,Ctrl+C退出脚本"
char=`get_char`
echo $iptablesshell >> $iptablesconf
runreturn=`$iptablesshell`
echo $runreturn
echo '配置添加成功'
}
function add_confs(){
rootness
conf_add
}
function del_conf(){
echo
while true
do
echo "请输入宿主机的端口"
read -p "(默认操作: 退出):" confserverport
[ -z "$confserverport" ] && exit 1
expr $confserverport + 0 &>/dev/null
if [ $? -eq 0 ]; then
if [ $confserverport -ge 1 ] && [ $confserverport -le 65535 ]; then
echo
echo "宿主机端口 = $confserverport"
echo
break
else
echo "输入错误,端口范围应为1-65535!"
fi
else
echo "输入错误,端口范围应为1-65535!"
fi
done
echo
iptablesshelldel=`cat $iptablesconf | grep "dport $confserverport"`
if [ ! -n "$iptablesshelldel" ]; then
echo "配置文件中没有该宿主机的端口"
exit 1
fi
iptablesshelldelshell=`echo ${iptablesshelldel//-A/-D}`
runreturn=`$iptablesshelldelshell`
echo $runreturn
sed -i "/$iptablesshelldel/d" $iptablesconf
echo '配置删除成功'
}
function del_confs(){
printf "你确定要删除配置吗?操作是不可逆的(y/n) "
printf "\n"
read -p "(默认: n):" answer
if [ -z $answer ]; then
answer="n"
fi
if [ "$answer" = "y" ]; then
rootness
del_conf
else
echo "配置删除操作取消"
fi
}
action=$1
case "$action" in
add)
add_confs
;;
list)
conf_list
;;
del)
del_confs
;;
*)
echo "参数错误! [${action} ]"
echo "用法: `basename $0` {add|list|del}"
;;
esac