多节点通过PPPoSSH连接,节点/用户/客户机之间互相访问ping
转载注明来源: 本文链接 来自osnosn的博客,写于 2019-04-14.
背景
有A, B, C 三台客户机,通过ppp虚拟拨号连接到服务器。
- 搜索"ppp over ssh"
- VPN PPP-SSH Mini-HOWTO
- Poor man's VPN using PPP over SSH
- VPN over SSH
发现A, B, C分别能访问服务器,但A,B,C之间不能互访,不能互ping,即使ppp的IP都配置到一个网段。
配置的关键点
经过反复测试,解决问题,A,B,C之间可以互相ping通,互相访问了。
以下是配置的关键点:
-
server:
- 打开内核IP转发
sysctl -w net.ipv4.ip_forward=1
可以在/etc/sysctl.conf
中设置。 - 开放iptables的转发规则,允许转发
iptables -A FORWARD -s 192.168.33.0/24 -d 192.168.33.0/24 -j ACCEPT
如果你的服务器是centos8,使用了nft,见下文,nft设置转发规则。 - 允许接收此网段的数据包(可选)
iptables -A INPUT -s 192.168.33.0/24 -d 192.168.33.0/24 -j ACCEPT
- 禁止此网段的数据包(TCP),从物理网口出去(可选)
iptables -A OUTPUT -p tcp -o eth0 -d 192.168.33.0/24 -j REJECT --reject-with tcp-reset
如果你的服务器是centos8,使用了nft,见下文,nft设置reject规则。 - 禁止此网段的数据包(其他类型的包),从物理网口出去(可选)
iptables -A OUTPUT -o eth0 -d 192.168.33.0/24 -j REJECT --reject-with icmp-host-prohibited
- 打开内核IP转发
-
client: (每个客户端都需要加上192.168.33.0/24的路由)
#!/bin/sh -e # debain: copy this file to "/etc/ppp/ip-up.d/" , and chmod +x file. # centos: append this lines to "/etc/ppp/ip-up.local" , and chmod +x ip-up.local # openwrt:append this lines to "/etc/ppp/ip-up" , and chmod +x ip-up # PPP_IFACE="$1", PPP_LOCAL="$4", PPP_REMOTE="$5" if [ "$5" = "192.168.33.1" ]; then #根据对端/服务端的IP设置。我的例子是33.1 #/sbin/ip route add 192.168.33.0/24 via $5 dev $1 proto static /sbin/ip route add 192.168.33.0/24 via $5 proto static fi exit 0
nft设置转发规则
- centos8,默认使用nft作为防火墙。开启net.ipv4.ip_forward=1之后。
你会发现A,B,C直接可以ping通。但不能traceroute,不能互相访问端口,会得到No route to host
的错误。 - 方法一:
- 首先
nft -a list ruleset | less
找到 `table inet firewalld{ chain filter_FORWARD { } } 中最后一条规则的handle。在我机器上是147。table inet firewalld { # handle 17 ... chain filter_FORWARD { # handle 120 ... reject with icmpx type admin-prohibited # handle 147 } ... }
- 执行
nft insert rule inet firewalld filter_FORWARD handle 147 ip saddr 192.168.33.0/24 ip daddr 192.168.33.0/24 accept
- 如果要删除这条规则,先
nft -a list ruleset
找到之前加入的规则的handle,比如是258。
执行nft delete rule inet firewalld filter_FORWARD handle 258
- 首先
- 方法二:
- 因为filter_FORWARD_IN_ZONES_SOURCE是个空chain,直接执行
nft add rule inet firewalld filter_FORWARD_IN_ZONES_SOURCE ip saddr 192.168.33.0/24 ip daddr 192.168.33.0/24 accept
- 删除的方法类似,先找handle,再删除。
nft delete rule inet firewalld filter_FORWARD_IN_ZONES_SOURCE handle 259
- 因为filter_FORWARD_IN_ZONES_SOURCE是个空chain,直接执行
- 方法三:
- 因为filter_FWDI_public_allow也是个空chain,直接执行
nft add rule inet firewalld filter_FWDI_public_allow ip saddr 192.168.33.0/24 ip daddr 192.168.33.0/24 accept
- 因为filter_FWDI_public_allow也是个空chain,直接执行
- 以上三种办法,任选一种即可。都是基于CentOS8,firewalld启动后的默认nft表。
CentOS8的默认表,请看: 关于 iptables 和 nftables 在 CentOS 新版本的使用
使用 firewall-cmd 命令添加转发规则的办法,
- firewalld官网说,firewall-cmd-0.9.0 才支持
--add-forward
参数。
centos8的firewall-cmd版本还是 0.8.0,所以不支持给nft加入forward规则。 - 如果把这个 add rule 指令放在 /etc/rc.local 也不行. 因为 rc.local 执行时,firewalld 还没建立好规则表。
只能等机器启动好,再登录上去,手工添加这条规则。 - 为了免去手工登录,手工添加。只好创建个脚本,放入root的crontab中,60分钟执行一次。
脚本先检查firewalld的规则表是否已经建立,再检查forward规则是否已经加入。如果没有加入,则添加。
nft设置reject规则 (禁止此网段的TCP数据包,从物理网口出去) (可选)
/usr/sbin/nft add rule inet firewalld filter_OUTPUT meta oifname "eth0" ip protocol tcp ip daddr 192.168.33.0/24 reject with tcp reset
PPPoSSH 配置过程备份
服务端
- 如果用于 FreeBSD,脚本需要修改。使用ppp 命令,不是pppd。
可以不用 sudo,可以配置允许普通用户执行ppp,好像是将用户加入特定的group(忘了)。 - 本次测试使用的是 debian-11 系统,需要
apt install ppp sudo
- 创建单独的用户,比如 vpps, 指定uid,gid。
addgroup --gid 3000 vpps; adduser --uid 3000 --gid 3000 vpps
visudo
增加一行,让 vpps用户可以执行 pppd命令。
可以插入在任意一行。这一行中的空格,可以任意多个。vpps ALL=(root) NOPASSWD: /usr/sbin/pppd
- 创建密钥登陆所需文件,为了免密登陆。
此文件内容为了免密登陆。具体内容自行编辑添加。cd ~vpps/; mkdir .ssh; chown vpps.vpps .ssh; chmod 700 .ssh cd ~vpps/.ssh; touch authorized_keys chown vpps.vpps authorized_keys; chmod 600 authorized_keys
- 用
vipw -s
修改 vpps用户的密码部分为 "*", 即,任何密码都无法登陆。 - 用
vipw
修改 vpps用户的shell为 "/home/vpps/bin/shell"。 - 创建脚本文件"~vpps/bin/shell",内容为下面的"shell for vpps"的内容,
chmod +x ~vpps/bin/shell
。
此脚本,对登录成功后, 可以执行的命令,有一定的限制。#!/bin/sh # shell for vpps , server #echo "$*" >> /home/vpps/log if [ -z "$*" ];then echo 'Login succeed.' exit 0 fi a="`expr "$*" : '-c /usr/bin/sudo /usr/sbin/pppd '`" #Linux中,普通用户执行pppd b="`expr "$*" : '-c /usr/sbin/ppp -direct '`" #FreeBSD中,用户执行ppp g="`expr "$*" : '-c sudo /usr/sbin/pppd '`" #Linux中,普通用户执行pppd h="`expr "$*" : '-c /usr/sbin/pppd '`" #Linux中,root用户登录,执行pppd if [ "$a" = "32" -o "$b" = "25" -o "$g" = "23" -o "$h" = "18" ] ;then a="`expr "$*" : '-c \(.*\)'`" # eval "$a" exec $a # echo "$a" fi exit 0 logout
- add_forward_rule.sh (非必需) 在服务端运行。此脚本合适centos8。
如用于debian,因为系统的规则 chain不同,需要更改,规则插入的位置。#!/bin/bash # 此程序没有检查 chain 是否存在。 fwd_chain=$( /sbin/nft -a list chain inet firewalld filter_FWDI_public_allow ) fwd_rule=$( echo "${fwd_chain}" |/bin/grep 'ip saddr 192.168.33.0/24' ) if [ -n "${fwd_chain}" -a -z "${fwd_rule}" ]; then echo 'add forward rule.' # 此命令,无论是放在 /etc/rc.local 还是放在 root的crontab @reboot项 # 执行的时机都早于 firewalld 创建缺省规则表。导致添加失败。 # firewalld not started, so add rule fail. /usr/sbin/nft add rule inet firewalld filter_FWDI_public_allow ip saddr 192.168.33.0/24 ip daddr 192.168.33.0/24 accept else echo 'already have forward rule.' echo "$fwd_chain" echo 'to delete:' #echo ' nft delete rule inet firewalld filter_FWDI_public_allow handle xx' IFS=$'\n'; for cc in "$fwd_rule"; do echo "$cc"|/bin/awk -F'#' '{print " nft delete rule inet firewalld filter_FWDI_public_allow" $2}' done fi
客户端-使用脚本
- 客户端脚本,可用于所有linux系统。如 Debian, CentOS, OpenWRT。
如果用于 FreeBSD,脚本需要修改。使用ppp 命令,不是pppd。 - 把前面提到的 client 用的 ip-up 脚本,根据不同系统放入
/etc/ppp/
对应的位置。 - 执行
sh vpn-pppssh.sh {start|stop|config}
#!/bin/sh # vpn-pppssh.sh , client #### check hostkey in file ".ssh/known_hosts" ##### LINK_NAME=my-ppp-vpn LINK_PEER_NAME=my-ppp-vpn SERVER_HOSTNAME=6.6.6.6 SERVER_SSH_PORT=22 SERVER_USERNAME=vpps SERVER_IFIPADDR=192.168.33.1 #fix IP CLIENT_IFIPADDR=192.168.33.13 LOCAL_SSH_OPTS="-P" PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/bin/X11/: PPPD=/usr/sbin/pppd SSH=/usr/bin/ssh if ! test -f $PPPD ; then echo "can't find $PPPD"; exit 3; fi if ! test -f $SSH ; then echo "can't find $SSH"; exit 4; fi case "$1" in start) # echo -n "Starting vpn to $SERVER_HOSTNAME: " ${PPPD} ipparam ${LINK_NAME} updetach noauth passive pty "${SSH} ${LOCAL_SSH_OPTS} ${SERVER_HOSTNAME} -t -l${SERVER_USERNAME} -p ${SERVER_SSH_PORT} -o Batchmode=yes /usr/bin/sudo ${PPPD} nodetach noauth ipparam ${LINK_PEER_NAME} idle 3700" ${CLIENT_IFIPADDR}:${SERVER_IFIPADDR} nodefaultroute idle 1800 connect-delay 8000 # echo "connected." ;; stop) # echo -n "Stopping vpn to $SERVER_HOSTNAME: " PID=`ps ax | grep "${PPPD} ipparam ${LINK_NAME} updetach noauth passive" | grep -v 'grep ' | awk '{print $1}'` if [ "${PID}" != "" ]; then kill $PID echo "disconnected." else echo "Failed to find PID for the connection" fi ;; config) echo "LINK_NAME=$LINK_NAME" echo "LINK_PEER_NAME=$LINK_PEER_NAME" echo "SERVER_HOSTNAME=$SERVER_HOSTNAME" echo "SERVER_SSH_PORT=$SERVER_SSH_PORT" echo "SERVER_USERNAME=$SERVER_USERNAME" echo "SERVER_IFIPADDR=$SERVER_IFIPADDR" echo "CLIENT_IFIPADDR=$CLIENT_IFIPADDR" ;; *) echo "Usage: vpn-pppssh {start|stop|config}" exit 1 ;; esac exit 0
客户端-使用openwrt的luci
- 在openwrt-22.03上测试,对端为debian-11。2023-10测试OK。
- 需要安装
opkg install luci-proto-pppossh
,重启整个op生效。 - Network -> Interfaces -> Add New Interface... 点击创建新网口,Protocol 选择 PPPoSSH。
* General Settings - Protocol: PPPoSSH - Bring up on boot: 勾上 - SSH username: vpps #服务端的 ssh 用户名 - SSH server address: 6.6.6.6 #服务端的IP 或 域名, 见下面的说明。 - SSH server port: 22 #服务端ssh的端口 - Extra SSH command options: 留空,或 -y #见下面的说明。 - List of SSH key files for auth: /root/.ssh/id-xxx #写绝对路径。相对路径不行。见说明。 - Local IP address to assign: 192.168.33.14 #本地端,客户端的IP。 - Peer IP address to assign: 192.168.33.1 #对端,服务端的IP。 * Advanced Settings - Use default gateway: 不勾 - 其他选项: 默认 * Firewall Settings - 选择 LAN * DHCP Server - 不配置,不启用 DHCP server
- SSH server address: 如果使用域名
- 如果 openwrt 没有ipv6,则不支持双栈域名,即,域名只能有A记录,不能有AAAA记录。
也可以通过openwrt的设置,禁止ipv6解析,达到只有A记录的目的。
否则不连接,显示Error: Network device is not present
- 如果 op 有 ipv6,则没限制。
- 如果 openwrt 没有ipv6,则不支持双栈域名,即,域名只能有A记录,不能有AAAA记录。
- Extra SSH command options:
服务器的 host key,要在.ssh/know_hosts
文件中。
事先手工登录一次,ssh -p port user@myhost
出现提示时,输入 yes,把它加入 trusted hosts file.
或者,写入额外参数 -y 不验证服务器的 host key。 - List of SSH key files for auth:
op 默认的ssh客户端是 /usr/bin/dbclient 。
如果安装了 openssh-client 则会被替换为 /usr/libexec/ssh-openssh 。
这两个客户端需要的 identityfile 的格式是不同的。要注意。使用的文件,格式错误,则登录不上去。 - 根据需要,修改
/lib/netifd/proto/pppossh.sh
脚本。来自opkg files pppossh
。- 如果要指定使用 dbclient,修改它的第二行
SSH=/usr/bin/ssh
为SSH=/usr/bin/dbclient
。@@ -1,5 +1,5 @@ #!/bin/sh -SSH=/usr/bin/ssh +SSH=/usr/bin/dbclient [ -x "$SSH" ] || { echo "Cannot find executable $SSH." >&2
- 如果服务端是普通用户,需要sudo执行 pppd。则改,
@@ -61,5 +61,5 @@ opts="$opts ${ssh_options}" opts="$opts $sshuser@$server" - pty="exec env 'HOME=$home' $SSH $opts pppd nodetach notty noauth" + pty="exec env 'HOME=$home' $SSH $opts sudo /usr/sbin/pppd nodetach notty noauth" ppp_generic_setup "$config" noauth pty "$pty" "$ipaddr:$peeraddr"
- 如果要指定使用 dbclient,修改它的第二行
- Firewall Settings: 可以选择其他 ZONE,或者创新一个新的 ZONE。
参考【WireGuard_2和3台OpenWRT测试_LAN-LAN连接测试_Debian11_CentOS8】
---end---
转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/10703841.html 来自osnosn的博客.