文档中心 私有网络 最佳实践 配置云服务器为公网网关

配置云服务器为公网网关

最近更新时间:2019-12-09 18:25:18

注意:

2019年12月6日后,腾讯云将不支持在云服务器购买页勾选配置公网网关。如果您有需要,请按照本文所示方法自行配置。

操作场景

当您在腾讯云 VPC 中的部分云服务器没有普通公网 IP,但需要访问公网时,可以利用带有公网 IP(普通公网 IP 或弹性公网 IP) 的云服务器访问公网。公网网关云服务器将对出网流量进行源地址转换,所有其他云服务器访问公网的流量经过公网网关云服务器后,源 IP 都被转换为公网网关云服务器的公网 IP 地址,如下图所示:

前提条件

  • 已登录 云服务器控制台
  • 公网网关云服务器只能转发非所在子网的路由转发请求,因此,公网网关云服务器不能与需要借助公网网关访问公网的云服务器处于同一个子网下。
  • 公网网关云服务器必须为 Linux 云服务器,Windows 云服务器无法作为公网网关使用。

操作步骤

步骤1:绑定弹性公网 IP(可选)

说明:

如果用作公网网关的云服务器已经有公网 IP 地址,请跳过此步骤,完成后续步骤。

  1. 在左侧导航栏中,单击【弹性公网IP】,进入弹性公网 IP 管理页面。
  2. 在需要绑定实例的弹性公网 IP 的操作栏下,选择【更多】>【绑定】。
  3. 在“绑定资源”弹框中,选择一个被选做公网网关的 CVM 实例进行绑定。

步骤2:配置网关所在子网路由表

网关子网和普通子网不能关联同一张路由表,需要新建一张独立的网关路由表,并将网关子网关联该路由表。

  1. 创建自定义路由表
  2. 创建后会提示关联子网操作,直接关联公网网关服务器所在子网即可。

步骤3:配置普通子网路由表

配置普通子网的路由表,配置默认路由走公网网关云服务器,使得普通子网内的云服务器能通过公网网关的路由转发能力访问公网。
在普通云服务器所在子网的路由表中,新增如下路由策略:

  • 目的端:您要访问的公网地址。
  • 下一跳类型:云服务器。
  • 下一跳:步骤1中绑定弹性公网 IP 的云服务器实例的内网 IP。
    具体操作请参见 配置路由策略

步骤4:配置公网网关

  1. 登录公网网关云服务器,开启网络转发,NAT 代理功能,以及相关参数优化。

    1. 执行如下命令,在usr/local/sbin目录下新建脚本vpcGateway.sh

      vim /usr/local/sbin/vpcGateway.sh
    2. 按 “i” 切换至编辑模式,将如下代码写入脚本中:

      #!/bin/bash
      echo "----------------------------------------------------"
      echo "          `date`"
      
      echo "(1)ip_forward config......"
      file="/etc/sysctl.conf"
      grep -i "^net\.ipv4\.ip_forward.*" $file &>/dev/null && sed -i \
      's/net\.ipv4\.ip_forward.*/net\.ipv4\.ip_forward = 1/' $file || \
      echo "net.ipv4.ip_forward = 1"  >> $file
      echo 1 >/proc/sys/net/ipv4/ip_forward 
      [ `cat /proc/sys/net/ipv4/ip_forward` -eq 1 ] && echo "-->ip_forward:Success" || \
      echo "-->ip_forward:Fail"
      
      echo "(2)Iptables set......"
      iptables -t nat -A POSTROUTING -j MASQUERADE && echo "-->nat:Success" || echo "-->nat:Fail"
      iptables -t mangle -A POSTROUTING -p tcp -j TCPOPTSTRIP --strip-options timestamp && \
      echo "-->mangle:Success" || echo "-->mangle:Fail"
      
      echo "(3)nf_conntrack config......"
      echo 262144 >  /sys/module/nf_conntrack/parameters/hashsize
      [ `cat /sys/module/nf_conntrack/parameters/hashsize` -eq 262144 ] && \
      echo "-->hashsize:Success" ||  echo "-->hashsize:Fail"
      
      echo 1048576 > /proc/sys/net/netfilter/nf_conntrack_max
      [ `cat /proc/sys/net/netfilter/nf_conntrack_max` -eq 1048576 ] && \
      echo  "-->nf_conntrack_max:Success" ||  echo  "-->nf_conntrack_max:Fail"
      
      echo 10800 >/proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established \
      [ `cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established` -eq 10800 ] \
      && echo  "-->nf_conntrack_tcp_timeout_established:Success" ||  \
      echo  "-->nf_conntrack_tcp_timeout_established:Fail"
    3. 按 “Esc”,输入 “:wq”,保存文件并返回后,执行如下命令:

        chmod +x /usr/local/sbin/vpcGateway.sh
        echo "/usr/local/sbin/vpcGateway.sh  >/tmp/vpcGateway.log 2>&1" >> /etc/rc.local
  2. 设置公网网关的 rps:

    1. 执行如下命令,在usr/local/sbin目录下新建脚本set_rps.sh

      vim /usr/local/sbin/set_rps.sh
    2. 按 “i” 切换至编辑模式,将如下代码写入脚本中:

      #!/bin/bash
      echo "--------------------------------------------"
      date
      mask=0
      i=0
      total_nic_queues=0
      
      get_all_mask() {
            local cpu_nums=$1
            if [ $cpu_nums -gt 32 ]; then
                    mask_tail=""
                    mask_low32="ffffffff"
                    idx=$((cpu_nums / 32))
                    cpu_reset=$((cpu_nums - idx * 32))
      
                    if [ $cpu_reset -eq 0 ]; then
                            mask=$mask_low32
                            for ((i = 2; i <= idx; i++)); do
                                    mask="$mask,$mask_low32"
                            done
                    else
                        for ((i = 1; i <= idx; i++)); do
                            mask_tail="$mask_tail,$mask_low32"
                    done
                    mask_head_num=$((2 ** cpu_reset - 1))
                    mask=$(printf "%x%s" $mask_head_num $mask_tail)
                fi
            else
                mask_num=$((2 ** cpu_nums - 1))
                mask=$(printf "%x" $mask_num)
            fi
            echo $mask
      }
      set_rps() {
          if ! command -v ethtool &>/dev/null; then
            source /etc/profile
          fi
      
          ethtool=$(which ethtool)
      
          cpu_nums=$(cat /proc/cpuinfo | grep processor | wc -l)
          if [ $cpu_nums -eq 0 ]; then
              exit 0
          fi
      
          mask=$(get_all_mask $cpu_nums)
          echo "cpu number:$cpu_nums  mask:0x$mask"
      
          ethSet=$(ls -d /sys/class/net/eth*)
      
          for entry in $ethSet; do
              eth=$(basename $entry)
              nic_queues=$(ls -l /sys/class/net/$eth/queues/ | grep rx- | wc -l)
              if (($nic_queues == 0)); then
                  continue
              fi
      
              cat /proc/interrupts | grep "LiquidIO.*rxtx" &>/dev/null
              if [ $? -ne 0 ]; then # not smartnic
                  #multi queue don't set rps
                  max_combined=$(
                      $ethtool -l $eth 2>/dev/null | grep -i "combined" | head -n 1 | awk '{print $2}'
                  )
                  #if ethtool -l $eth goes wrong.
                  [[ ! "$max_combined" =~ ^[0-9]+$ ]] && max_combined=1
                  if [ ${max_combined} -ge ${cpu_nums} ]; then
                      echo "$eth has equally nic queue as cpu, don't set rps for it..."
                      continue
                  fi
              else
                 echo "$eth is smartnic, set rps for it..."
              fi
      
              echo "eth:$eth  queues:$nic_queues"
              total_nic_queues=$(($total_nic_queues + $nic_queues))
              i=0
              while (($i < $nic_queues)); do
                  echo $mask >/sys/class/net/$eth/queues/rx-$i/rps_cpus
                  echo 4096 >/sys/class/net/$eth/queues/rx-$i/rps_flow_cnt
                    i=$(($i + 1))
             done
          done
      
          flow_entries=$((total_nic_queues * 4096))
          echo "total_nic_queues:$total_nic_queues  flow_entries:$flow_entries"
          echo $flow_entries >/proc/sys/net/core/rps_sock_flow_entries
      }
      set_rps
    3. 按 “Esc”,输入 “:wq”,保存文件并返回后,执行如下命令:

      chmod +x /usr/local/sbin/set_rps.sh
      echo "/usr/local/sbin/set_rps.sh >/tmp/setRps.log 2>&1" >> /etc/rc.local
  3. 完成上述配置后,重启公网网关云服务器使配置生效,并在无公网 IP 的云服务器上,测试是否能够成功访问公网。