多网卡Linux做软路由
背景
电信宽带:家里是电信宽带。
公网ip:电信打10000找人工客服是可以给公网ip (ipv4),ipv6默认就给的。但是这个公网ip是动态分配的,可能过两天就变成了另一个ip地址。
DDNS:用域名+dnspod接口+shell脚本实现ddns。
电信光猫上配置DMZ主机, 或配置端口映射。
以上(公网IP+DDNS动态域名绑定+内网端口映射),可以将内网服务暴露到公网。通过域名:端口
访问,基本可以满足日常需求。
问题
但是使用过程中遇到以下几个问题:
- DMZ的那台主机是我的个人台式电脑,偶尔也是会关闭电脑的。像代理之类的服务,我希望可以长期稳定。
- 内网端口映射可能会变动,从外网很访问光猫调整配置受到限制。
预期
因此就打算买一台多网卡小主机做软路由,常用的服务直接放到这台小主机上面。
光猫改桥接,光猫LAN直连小主机某个网卡接口,比如enp2s0。
家庭网络(局域网)中的其他设备通过交换机互相连接,最后连接到小主机另一个网卡接口,比如enp3s0 。
小主机负责如下功能:
- 使用ppp协议和ISP拨号连接。因为小主机网卡接口是以太网,所以实际使用的协议是PPPoE (PPP over Ethernet)
- 数据路由和NAT。根据其功能,也称这样的小主机为软路由。
- 向家庭网络其他设备提供DHCP服务。(略,我是直接采购了无线AC和AP,DHCP服务由AC控制器负责了)。
准备
多网卡小主机(我是淘宝搜软路由,下单了一台 N5105,4个千兆接口)
小主机装Linux系统(我是直接让发货前预装CentOS, 厂家给装的CentOS7. )最后写文章的时候改成了CentOS stream 8, 没啥区别,但都是redhat系,其他linux 配置可能会略有区别。
netfilter/iptables基本概念和命令(尤其是数据在网卡,网络stack,四表五链间的传输过程)
实践
配置
开启内核转发
(重启仍生效需要写到配置文件)
cat /proc/sys/net/ipv4/ip_forward
#编辑这个文件
vim /etc/sysctl.conf
# 增加如下配置
net.ipv4.ip_forward = 1
重启linux
shutdown -r now
添加pppoe拨号配置
根据centos
pppoe
路由器
找到下面这个帖子,是使用cli菜单添加的dsl配置。(nmtui命令)
参考这个:CentOS 8 下配置 PPPoE 拨号上网 – 黑山雁 – 博客园 (cnblogs.com)
以及这个:
http://www.360doc.com/content/22/0608/15/65839694_1035172190.shtml
用nmtui创建了adsl配置,安装了NetworkManager-ppp依赖。
没参考这个,但是很受震撼: https://www.jianshu.com/p/1265004c2922
安装iptables
yum install iptables
备份并清空初始规则
备份自带的规则,清空重建
//备份iptables原始规则
mkdir /etc/iptables
iptables-save > /etc/iptables/rule.v4_origin
//删除用户定义的规则
iptables -F
//删除用户定义的链
iptables -X
iptables软路由规则
Centos实现软路由 参考了点这个, 但是没有pppoe拨号的相关内容。只适用于局域网两个网段的转发。当然,用路由表也可以。 但是这个文章的iptables配置有不符合需求的地方(因为ppp拨号后,动态获取的公网ip,需要动态伪装MASQURADING)。
百度出来乱糟糟的, google了一下,这篇不错:
How to Turn a Linux Server into a Router to Handle Traffic Statically and Dynamically – Part 10
将的很有条理, 还讲了pppoe的情况。iptables大概要类似这样的配置。
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
# iptables -A FORWARD -i ppp0 -o enp3s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i enp3s0 -o ppp0 -j ACCEPT
前面清掉了iptables已有规则,所以这几条规则其实是iptables最前面的规则。注意!!!
这几条规则大概意思是:
- 从 ppp0出去的数据自动做源地址映射(从局域网向公网发出的数据包 step2)(记录临时的映射表里,这种行为叫masquerade)
- 如果数据是从ppp0进来,向enp3s0出去(从公网向局域网发回的数据包), 并且是已建立的链路(tcp有类似建立session的概念,udp也会在临时记录表里有一段时间的记录),允许通过。
- 从enp3s0进来,向ppp0出去的数据包,(从局域网向公网发出的数据包 step1)直接放行。
如果要做暴露路由器上某个端口到公网,以及将局域网某个主机端口映射到路由器上某个端口,则需要进一步的iptables配置。这里先不管,先让局域网能上公网再说。
关防火墙
很多人配到这里就可以用了。很奇怪,我这边还是不行。灵光一闪,是不是防火墙的问题?
//查看防火墙状态
iptables status firewalld
//看到是开着的。。。
//先关掉看看,是不是这个问题
iptables stop firewalld
iptables disable firewalld
关SELinux
还是不行,局域网内主机有极小概率能ping通以下公网,网页打不开。又灵光一闪,是不是selinux开着?
//看下默认配置,是不是开着
vi /etc/selinux/config
//看到一行:SELINUX=enforcing
//改为:SELINUX=disabled
//备份iptables规则
iptables-save > /etc/iptables/rule.v4_20230216_2335
//重启服务器
shutdown -r now
//重启后可以看到,iptables规则已经重置
iptables -L -v
//删除用户定义的规则
iptables -F
//删除用户定义的链
iptables -X
//使用关机前的iptables规则
iptables-restore /etc/iptables/rule.v4_20230216_2335
出现了一个奇怪的问题, 百度能打开(正常),搜索也有结果(正常),但是点击搜索结果,进入页面一直刷新不完整(异常)。
调整ppp包的MSS大小
百思不得其解, google搜索 pppoe nat iptables 三个关键字,下面这边文章给多讲了一点底层的逻辑:
How to Setup a Linux Firewall with PPPoE/NAT/iptables
根据对方给的思路,估摸着大概是PPPoE有附加的字节, **Maximum Segment Size (MSS)**超了。
果然,注意到对方末尾例子中有如下几行, 但是是注释状态。
//...
IPTABLES="iptables"
//...
# echo "Mainly for PPPoE, VPN and DSL (MTU Fix, activate it if you have)"
# echo "Problems with large Downloads over PPPoE"
# $IPTABLES -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# $IPTABLES -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
google搜了下末尾两行, 找到一篇相关的文章,也是说是MSS的问题:
文章说:
iptables -A FORWARD-p tcp- -tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
该规则的目的就是改变TCP MSS以适应PMTU(Path MTU)
反正大概就是协议设计的时候没多考虑中间插了一层ppp,包头变大了,能传输的数据要比默认的MTU小一些才行。或者可以自动协商。
试着在这两条链前面加上这两个规则,
iptables -I OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
有网了,打完收工。
对了nmtui配置adsl连接的时候,好像也有MSS大小的设置项,可以设小一点试试,说不定可以不用加上面的规则(没去试,不确定)。
设置开机自动restore我们的iptables规则
等等,还记得前面重启电脑,我们写的iptables规则自动丢失了吗。需要改为开机自动restore为我们自己的规则的。
可以自己写个启动脚本,也有现成的。参考:https://blog.csdn.net/Victor2code/article/details/105768946
iptables 重启会失效,需要持久化写好的规则,做成服务启动时加载。
yum install iptables-services
//把我们之前备份的规则复制一份到特定位置
cp /etc/iptables/rules.v4 /etc/sysconfig/iptables
//启动对应的服务
systemctl start iptables.service
systemctl enable iptables.service
多网卡默认网关的问题
多网卡默认网关的问题。
前面ppp的配置也算是与NetworkManager那一套网络工具配套的(nmtui创建了adsl配置,安装了NetworkManager-ppp依赖),
我的软路由的enp2s0接口接了公网(光纤-光猫-接出来的WAN口)。
我的ppp0配置是建立在enp2s0接口之上的,ppp0的ip是ISP动态分配的。
内网连了软路由的enp3s0接口,使用固定ip 192.168.1.1,掩码255.255.255.0,这个直接在desktop的gui界面设置好了(之后这里有个小问题,会自动在对应的配置文件中写入GATEWAY信息)。
这时ip route show
命令查看路由表,就会发现,有两条默认网关。而每次启动,这两条默认网关前后顺序是随机的。需要把enp3s0接口的默认网关去掉,否则默认网关可能走了192.168.1.1而不是公网网关。
vim /etc/sysconfig/network-scripts/ifcfg-enp3s0
//用#注释掉GATEWAY一行
#GATEWAY=192.168.1.1
最后提供一份成型的iptables规则备份
[root@localhost ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*filter
:INPUT ACCEPT [5241:1345465]
:FORWARD ACCEPT [8114:591767]
:OUTPUT ACCEPT [8841:914546]
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -i ppp0 -o enp3s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i enp3s0 -o ppp0 -j ACCEPT
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*security
:INPUT ACCEPT [3797:362810]
:FORWARD ACCEPT [64:87552]
:OUTPUT ACCEPT [8841:914546]
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*raw
:PREROUTING ACCEPT [23642:2589162]
:OUTPUT ACCEPT [8841:914546]
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*mangle
:PREROUTING ACCEPT [23642:2589162]
:INPUT ACCEPT [5241:1345465]
:FORWARD ACCEPT [18344:1239420]
:OUTPUT ACCEPT [8841:914546]
:POSTROUTING ACCEPT [8929:1004924]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*nat
:PREROUTING ACCEPT [19749:2139220]
:INPUT ACCEPT [13:3286]
:POSTROUTING ACCEPT [30:3747]
:OUTPUT ACCEPT [45:3478]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -o ppp0 -j MASQUERADE
-A POSTROUTING -o ppp0 -j MASQUERADE
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
配置DDNS
家里用的是电信宽带。打电话10000要客服给了ipv4公网地址,但是公网地址是经常变的。
crond定时任务自动更新dns
后来从DnsPod买了个域名配 DDNS做动态域名解析。动态域名解析用的是DnsPod提供的接口和免费服务。家里192.168.1.7这台主机定时每15分钟,运行一次脚本,获取一下家里主机的公网ip,然后调用DnsPod接口更新域名解析 很显然,是动态域名解析失败了。
cd /usr/local
git clone git@github.com:rehiy/dnspod-shell.git
修改其中的配置文件。主要是调整这里的域名和dnspod账号的token。
dnspod账号token的说明,见这里: https://docs.dnspod.cn/account/dnspod-token/
[root@jingmin-kube-master1 dnspod-shell]# cd /usr/local/dnspod-shell/
[root@jingmin-kube-master1 dnspod-shell]# ls
ardnspod ddnspod.sh README.md
[root@jingmin-kube-master1 dnspod-shell]# cat ddnspod.sh
#!/bin/sh
#
# Import ardnspod functions
. /usr/local/dnspod-shell/ardnspod
# Combine your token ID and token together as follows
#arToken="12345,7676f344eaeaea9074c123451234512d"
arToken="322277,9883b5824e52246cd72bc17c2f80d214"
# Force to use third party API to get IP or not
forceUseThirdApi=false
# Place each domain you want to check as follows
# you can have multiple arDdnsCheck blocks
# IPv4:
#arDdnsCheck "test.org" "subdomain"
#arDdnsCheck "ole12138.top" "www"
arDdnsCheck "ole12138.top"
# IPv6:
#arDdnsCheck "ole12138.top" "@" 6
看下ardnspod
root@jingmin-kube-master1 dnspod-shell]# cat ardnspod
[#!/bin/sh
#
#############################################################
# AnripDdns v6.1.1
#
# Dynamic DNS using DNSPod API
#
# Author: Rehiy, https://github.com/rehiy
# https://www.anrip.com/?s=dnspod
# Collaborators: ProfFan, https://github.com/ProfFan
#
# Usage: please refer to `ddnspod.sh`
#
#############################################################
# TokenID,Token
export arToken=""
# Force to use third party API to get IP or not
export forceUseThirdApi=false
# Get WAN IPv4
arWanIp4() {
local hostIp
local lanIps="^$"
lanIps="$lanIps|(^10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)"
lanIps="$lanIps|(^127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)"
lanIps="$lanIps|(^169\.254\.[0-9]{1,3}\.[0-9]{1,3}$)"
lanIps="$lanIps|(^172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}$)"
lanIps="$lanIps|(^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$)"
case $(uname) in
'Linux')
hostIp=$(ip -o -4 addr list | grep -Ev '\s(docker|lo)' | awk '{print $4}' | cut -d/ -f1 | grep -Ev "$lanIps")
;;
|FreeBSD)
DarwinhostIp=$(ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | grep -Ev "$lanIps")
;;
esac
if [ -z "$hostIp" -o "$forceUseThirdApi" = true ]; then
if type wget >/dev/null 2>&1; then
hostIp=$(wget -q -O- https://v4.myip.la)
else
hostIp=$(curl -s https://v4.myip.la)
fi
fi
if [ -z "$hostIp" ]; then
echo "arWanIp4 - Can't get ip address"
return 1
fi
if [ -z "$(echo $hostIp | grep -E '^[0-9\.]+$')" ]; then
echo "arWanIp4 - Invalid ip address $hostIp"
return 1
fi
echo $hostIp
}
# Get WAN IPv6
arWanIp6() {
local hostIp
local lanIps="(^$)|(^::1$)|(^[fF][eE][8-9a-fA-F])"
case $(uname) in
'Linux')
hostIp=$(ip -o -6 addr list | grep -Ev '\s(docker|lo)' | awk '{print $4,substr($NF,0,length($NF)-3)}' | sed 's/fore/2592000/g' | sort -k 2 -n | cut -d/ -f1 | grep -Ev "$lanIps" | head -n 1)
;;
|FreeBSD)
DarwinhostIp=$(ifconfig | grep "inet6 " | awk '{print $2}' | grep -Ev "$lanIps" | head -n 1)
;;
esac
if [ -z "$hostIp" -o "$forceUseThirdApi" = true ]; then
if type wget >/dev/null 2>&1; then
hostIp=$(wget -q -O- https://v6.myip.la)
else
hostIp=$(curl -s https://v6.myip.la)
fi
fi
if [ -z "$hostIp" ]; then
echo "arWanIp6 - Can't get ip address"
return 1
fi
if [ -z "$(echo $hostIp | grep -E '^[0-9a-fA-F:]+$')" ]; then
echo "arWanIp6 - Invalid ip address"
return 1
fi
echo $hostIp
}
# Dnspod Bridge
# Args: type data
arDdnsApi() {
local agent="AnripDdns/6.1.0(wang@rehiy.com)"
local apiurl="https://dnsapi.cn/${1:?'Info.Version'}"
local params="login_token=$arToken&format=json&$2"
if type wget >/dev/null 2>&1; then
wget -q -O- --no-check-certificate -U $agent --post-data $params $apiurl
else
curl -s -A $agent -d $params $apiurl
fi
}
# Fetch Ids of Domain and Record
# Args: recordType domain subdomain
arDdnsIds() {
local errMsg
local domainId
local recordId
# Get Domain Id
domainId=$(arDdnsApi "Domain.Info" "domain=$2")
domainId=$(echo $domainId | sed 's/.*"id":"\([0-9]*\)".*/\1/')
if ! [ "$domainId" -gt 0 ] 2>/dev/null ;then
errMsg=$(echo $domainId | sed 's/.*"message":"\([^\"]*\)".*/\1/')
echo "arDdnsIds - $errMsg"
return 1
fi
# Get Record Id
recordId=$(arDdnsApi "Record.List" "domain_id=$domainId&sub_domain=$3&record_type=$1")
recordId=$(echo $recordId | sed 's/.*"id":"\([0-9]*\)".*/\1/')
if ! [ "$recordId" -gt 0 ] 2>/dev/null ;then
errMsg=$(echo $recordId | sed 's/.*"message":"\([^\"]*\)".*/\1/')
echo "arDdnsIds - $errMsg"
return 1
fi
echo $domainId $recordId
}
# Fetch Record Ip
# Args: domainId recordId
arDdnsRecordIp() {
local errMsg
local recordIp
# Get Record Ip
recordIp=$(arDdnsApi "Record.Info" "domain_id=$1&record_id=$2")
recordIp=$(echo $recordIp | sed 's/.*,"value":"\([0-9a-fA-F\.\:]*\)".*/\1/')
# Output Record Ip
case "$recordIp" in
)
[0-9a-fA-F]*echo $recordIp
return 0
;;
)
*errMsg=$(echo $recordIp | sed 's/.*"message":"\([^\"]*\)".*/\1/')
echo "arDdnsRecordIp - $errMsg"
return 1
;;
esac
}
# Update Record Ip
# Args: domainId recordId subdomain hostIp recordType
arDdnsUpdate() {
local errMsg
local recordRs
local recordIp
local recordCd
if [ -z "$5" ]; then
echo "arDdnsUpdate - Args number error"
return 1
fi
# Update Ip
recordRs=$(arDdnsApi "Record.Modify" "domain_id=$1&record_id=$2&sub_domain=$3&record_type=$5&value=$4&record_line=%e9%bb%98%e8%ae%a4")
recordIp=$(echo $recordRs | sed 's/.*,"value":"\([0-9a-fA-F\.\:]*\)".*/\1/')
recordCd=$(echo $recordRs | sed 's/.*{"code":"\([0-9]*\)".*/\1/')
# Output Result
if [ "$recordIp" = "$4" ] && [ "$recordCd" = "1" ]; then
echo "arDdnsUpdate - success"
return 0
else
errMsg=$(echo $recordRs | sed 's/.*,"message":"\([^"]*\)".*/\1/')
echo "arDdnsUpdate - $errMsg"
return 1
fi
}
# DDNS Check
# Args: Main Sub
arDdnsCheck() {
local errCode
local recordType
local hostIp
local ddnsIds
local lastIp
local postRs
echo "Fetching Host Ip"
if [ "$3" = "6" ]; then
recordType=AAAA
hostIp=$(arWanIp6)
else
recordType=A
hostIp=$(arWanIp4)
fi
errCode=$?
echo "> Host Ip: $hostIp"
echo "> Record Type: $recordType"
if [ $errCode -ne 0 ]; then
return 1
fi
echo "Fetching Ids of $2.$1"
ddnsIds=$(arDdnsIds "$recordType" "$1" "$2")
errCode=$?
echo "> Domain Ids: $ddnsIds"
if [ $errCode -ne 0 ]; then
return 1
fi
echo "Checking Record for $2.$1"
lastIp=$(arDdnsRecordIp $ddnsIds)
errCode=$?
echo "> Last Ip: $lastIp"
if [ $errCode -ne 0 ]; then
return 1
fi
if [ "$lastIp" = "$hostIp" ]; then
echo "> Last Ip is the same as host Ip"
return 0
fi
echo "Updating Record for $2.$1"
postRs=$(arDdnsUpdate $ddnsIds "$2" "$hostIp" "$recordType")
errCode=$?
echo "> $postRs"
if [ $errCode -ne 0 ]; then
return 1
fi
}
域名解析脚本用的是别人提供的。
[root@archlinux dnspod-shell]# git remote -v
origin git@github.com:rehiy/dnspod-shell.git (fetch)
origin git@github.com:rehiy/dnspod-shell.git (push)
定时任务
[root@archlinux dnspod-shell]# crontab -l
*/15 * * * * /usr/local/dnspod-shell/ddnspod.sh
如果没有将日志重定向到单独的地方。 那就看下定时任务的系统日志
journalctl -u cronie
PPP重连后自动更新dns解析
参考:https://tldp.org/HOWTO/PPP-HOWTO/ip-up.html
After the link comes up – the /etc/ppp/ip-up
script
root@jingmin-kube-master1 ppp]# cd /etc/ppp
[root@jingmin-kube-master1 ppp]# ls
[chap-secrets eaptls-client eaptls-server ip-down ip-down.ipv6to4 ip-up ip-up.ipv6to4 ip-up.local ipv6-down ipv6-up options options.pptpd pap-secrets
root@jingmin-kube-master1 ppp]# cat ip-up
[#!/bin/bash
# This file should not be modified -- make local changes to
# /etc/ppp/ip-up.local instead
PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH
LOGDEVICE=$6
REALDEVICE=$1
[ -f /etc/sysconfig/network-scripts/ifcfg-${LOGDEVICE} ] && /etc/sysconfig/network-scripts/ifup-post --realdevice ${REALDEVICE} ifcfg-${LOGDEVICE}
/etc/ppp/ip-up.ipv6to4 ${LOGDEVICE}
[ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@"
exit 0
可知,我们需要编辑的是/etc/ppp/ip-up.local
[root@jingmin-kube-master1 ppp]# cat /etc/ppp/ip-up.local
#!/bin/bash
/usr/local/dnspod-shell/ddnspod.sh | mail -s "ppp reconnected" 784319947@qq.com
PPP重连后延迟重启远程服务器上的nginx
这是我的自定义配置,可忽略不看。
我有台服务器,上面开了nginx. 将其中某些流量转发到了家里的软路由上。
nginx 启动时缓存了域名解析,若要更新域名解析,默认需要重启nginx。
加入了 resolver配置,以及 valid选项,无效。(社区版nginx 这两个配置是无效的)
可以使用变量的方式(但无法使用upstream),也可以使用商业版nginx。
也可以ppp重连时,触发自动更新ddns域名脚本,也触发重启各主机上nginx的脚本。(或者crond定时重启nginx)
生成密钥对
ssh-keygen
公钥丢到要登录的远程服务器
//公钥丢到要登录的远程服务器
//输密码,复制
scp ./id_rsa.pub root@ole12138.cn:/root/.ssh/
//登录远程服务器
ssh root@ole12138.cn
//将刚刚上传的公钥追加到对应的文件/root/.ssh/authorized_keys 末尾
cd /root/.ssh
cat id_rsa.pub >> authorized_keys
//从远程服务器退出
exit
在本机尝试使用刚刚密钥对中的私钥登录远程服务器
ssh -i /root/.ssh/id_rsa root@ole12138.cn
参考: https://developer.aliyun.com/article/269047
参考: https://www.3mu.me/linux%E4%B8%AD%E7%9A%84shell%E7%94%A8ssh%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%8E%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E5%B9%B6%E8%87%AA%E5%8A%A8/
没问题后,远程执行命令
sleep 60 && ssh -i /root/.ssh/id_rsa root@ole12138.cn "nginx -s reload"
这里的意思是,暂停60s后,登陆远程服务器,重载一下nginx. (社区版nginx的stream中的resolver的valid配置无效,upstream中出现的域名解析,需要通过重载配置或重启nginx才能生效。)
将此内容追加到/etc/ppp/if-up.local
中去,ppp重连后,并更新dns后,60s后重启一下远程服务器上的nginx.
[root@jingmin-kube-master1 ppp]# vim /etc/ppp/ip-up.local
[root@jingmin-kube-master1 ppp]# cat /etc/ppp/ip-up.local
#!/bin/bash
/usr/local/dnspod-shell/ddnspod.sh | mail -s "ppp reconnected" 784319947@qq.com
sleep 60 && ssh -i /root/.ssh/id_rsa root@ole12138.cn "nginx -s reload"
最好在远程服务器上,也加个定时任务,保证域名解析能更新掉。
配置更新
配置专线
后来家里又拉了一条电信专线。原来的宽带也还在。
专线是固定ip. 宽带是pppoe拨号。
配置固定IP:专线插到路由器另一个网口。 用的nmtui命令,比较傻瓜式。
配置iptables转发:类似前面配置pppoe, 专线固定ip和内网的通信, 也需要配置iptables FORWARD链。并且NAT需要做MASQURADE.
这里直接给出最后的 /etc/sysconfig/iptables配置。 基本是在前面pppoe的配置上作了些改动。
[root@jingmin-kube-master1 ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*filter
:INPUT ACCEPT [5241:1345465]
:FORWARD ACCEPT [8114:591767]
:OUTPUT ACCEPT [8841:914546]
#-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -i ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
#-A OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A OUTPUT -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -i ppp0 -o enp3s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i enp3s0 -o ppp0 -j ACCEPT
-A FORWARD -i enp3s0 -o enp4s0 -j ACCEPT
-A FORWARD -i enp4s0 -o enp3s0 -j ACCEPT
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*security
:INPUT ACCEPT [3797:362810]
:FORWARD ACCEPT [64:87552]
:OUTPUT ACCEPT [8841:914546]
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*raw
:PREROUTING ACCEPT [23642:2589162]
:OUTPUT ACCEPT [8841:914546]
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*mangle
:PREROUTING ACCEPT [23642:2589162]
:INPUT ACCEPT [5241:1345465]
:FORWARD ACCEPT [18344:1239420]
:OUTPUT ACCEPT [8841:914546]
:POSTROUTING ACCEPT [8929:1004924]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
# Generated by iptables-save v1.8.4 on Thu Feb 16 23:38:34 2023
*nat
:PREROUTING ACCEPT [19749:2139220]
:INPUT ACCEPT [13:3286]
:POSTROUTING ACCEPT [30:3747]
:OUTPUT ACCEPT [45:3478]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -o ppp0 -j MASQUERADE
-A POSTROUTING -o enp4s0 -j MASQUERADE
COMMIT
# Completed on Thu Feb 16 23:38:34 2023
然后查看路由表
ip route show
可能会有两条默认路由。(nmtui配置时, 两个接口都允许作为默认路由的原因)。 我这里专线默认metric值低一点, 优先级更高, 不管了。
TODO
iptables端口映射
之前说到如果有暴露内网端口到公网的需求(向公网提供服务),前面提到的这边文章的代码中有例子,有需要可以看下。
How to Setup a Linux Firewall with PPPoE/NAT/iptables
也可以考虑使用nginx做tcp、udp转发。
若装docker可能会影响到现有规则
还有就是如果路由器上装了docker,好像会影响iptables。(docker好像自动加了些规则,可能要适配一下的)。 虽然路由器专机专用最好(Keep it simple and stupid),但是路由器有公网ip能ddns绑域名,而且软路由性能也过剩的。装个docker放点服务个人用用还是挺方便的。
后来装了docker,看起来暂时没啥问题。又装了k8s和flannel网络插件,也没啥问题。
内网使用公网ip访问内网服务的问题
NAT Lookback 与 Hairpin NAT
https://www.cnblogs.com/dream397/p/14522392.html
家庭网络公网ip封80端口的问题
注意:ddns+linux软路由网关,使家庭网络建站和向公网提供服务成为可能。但是注意:默认的80/443端口,运营商(电信)是封掉的。其他端口正常。
https://www.bilibili.com/read/cv15787877/
参考或待整理:
https://cn.bing.com/search?q=centos%20%E8%BD%AF%E8%B7%AF%E7%94%B1&qs=n&form=QBRE&pc=U316&sp=-1&pq=&sc=0-0&sk=&cvid=2424D4BA216F42818C39410E67DEA45E&ghsh=0&ghacc=0&ghpl=
https://blog.csdn.net/ichen820/article/details/115549050
https://www.jianshu.com/p/196e57a99a9a
https://cn.bing.com/search?q=route+%E5%92%8C+iptables+%E5%8C%BA%E5%88%AB&PC=U316&first=11&FORM=PORE
https://www.jianshu.com/p/653122f8433d
https://cn.bing.com/search?q=centos+dns+server&PC=U316&FORM=CHROMN
https://cloud.tencent.com/developer/article/1804618
https://www.cnblogs.com/travis-li/p/12908739.html
https://blog.csdn.net/wesleyflagon/article/details/80272696
https://cn.bing.com/search?q=linux+%e5%a4%9a%e7%bd%91%e5%8d%a1+%e8%bd%ac%e5%8f%91&qs=RI&pq=%e5%a4%9a%e7%bd%91%e5%8d%a1+%e8%bd%ac%e5%8f%91&sk=PRES1RI1&sc=2-6&cvid=245A9019D3E5492DA403E44DE47E83E8&FORM=QBRE&sp=2
发表回复