osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

多节点通过PPPoSSH连接,节点/用户/客户机之间互相访问ping

转载注明来源: 本文链接 来自osnosn的博客,写于 2019-04-14.

背景

有A, B, C 三台客户机,通过ppp虚拟拨号连接到服务器。

发现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
  • 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_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
  • 以上三种办法,任选一种即可。都是基于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,则没限制。
  • 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/sshSSH=/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"
      
  • Firewall Settings: 可以选择其他 ZONE,或者创新一个新的 ZONE。
    参考【WireGuard_2和3台OpenWRT测试_LAN-LAN连接测试_Debian11_CentOS8

---end---

转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/10703841.html 来自osnosn的博客.

posted on 2019-04-14 03:30  osnosn  阅读(1997)  评论(0编辑  收藏  举报