7、隧道工具

作者: Brinnatt 分类: ARM64 Linux CICD 研发 发布时间: 2025-01-18 09:39

7.1、openvpn

OpenVPN 官方地址:https://github.com/OpenVPN/openvpn

OpenVPN 的功能很强大,我们并没有深入研究该工具,按照以下步骤配置,基本上够用。

7.1.2、环境准备

软硬件版本

硬件 操作系统 软件
ARM64 ft2000+ centos7.5 easy-rsa3.0.6 openvpn2.4.7

软件安装源

# cat /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
baseurl=https://mirrors.aliyun.com/centos-altarch/$releasever/os/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=https://mirrors.aliyun.com/centos-altarch/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=https://mirrors.aliyun.com/centos-altarch/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
enabled=1

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=https://mirrors.aliyun.com/centos-altarch/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
# cat /etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

安装软件包

# yum install easy-rsa openvpn -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * epel: mirrors.yun-idc.com
Package easy-rsa-3.0.6-1.el7.noarch already installed and latest version
Package openvpn-2.4.7-1.el7.aarch64 already installed and latest version
Nothing to do

7.1.3、配置 easy-rsa 3.0.6

安装完 easy-rsa 3.0.6 后,默认会生成 easyrsa 脚本文件和 vars.example 环境变量文件,这两个文件是核心文件,找到这两个文件所在的目录,复制到相应的位置,然后根据自己的需求配置 vars

# find /usr/ -name easyrsa -o -name vars.example
/usr/share/doc/easy-rsa-3.0.6/vars.example
/usr/share/easy-rsa/3.0.6/easyrsa
# cp -r /usr/share/easy-rsa/3.0.6/ /etc/openvpn/3.0.6/
# cp /usr/share/doc/easy-rsa-3.0.6/vars.example /etc/openvpn/3.0.6/vars
# grep -v "^#\|^$" /etc/openvpn/3.0.6/vars
if [ -z "$EASYRSA_CALLER" ]; then
    echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2
    echo "This is no longer necessary and is disallowed. See the section called" >&2
    echo "'How to use this file' near the top comments for more details." >&2
    return 1
fi
set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE    "HuNan"
set_var EASYRSA_REQ_CITY    "ChangSha"
set_var EASYRSA_REQ_ORG "Greatwall Corporation"
set_var EASYRSA_REQ_EMAIL   "yuliangliang@greatwall.com.cn"
set_var EASYRSA_REQ_OU      "Product Department"
[root@openvpn ~]# 

7.1.3.1、easyrsa 命令使用

查看整体帮助
# ./easyrsa -h

查看某个子命令的详细帮助
# ./easyrsa help import-req

查看可以用到的 options
# ./easyrsa help options

7.1.3.2、创建 PKI 和 CA

# cd /etc/openvpn/3.0.6/
# ./easyrsa init-pki
# ls
easyrsa  openssl-easyrsa.cnf  pki  vars  x509-types
# ./easyrsa build-ca nopass (配置好了vars直接回车即可)

执行 ./easyrsa init-pki 后,EasyRSA 会在当前目录下创建一个名为 pki 的目录结构,包含以下内容:

  • pki/private:用于存放私钥文件,权限严格受限,确保密钥的安全。
  • pki/reqs:用于存放证书签名请求(CSR)。
  • pki/issued:用于存放签名后的证书(例如 .crt 文件)。
  • pki/certs_by_serial:存放按序列号命名的已签发证书(通常只在调试或跟踪中使用)。
  • pki/index.txt:一个索引文件,用于跟踪签发的所有证书。
  • pki/serial:一个文件,用于记录下一个将要分配的证书序列号。

命令 ./easyrsa build-ca nopass 是使用 EasyRSA 工具创建一个证书颁发机构(CA, Certificate Authority)的根证书和私钥。它是建立 PKI(公钥基础设施)中最重要的一步。

build-ca:子命令,表示创建一个证书颁发机构(CA)。

  • 该命令会生成 CA 的私钥和根证书。
  • CA 的主要作用是签署证书签名请求(CSR),生成可信任的服务器或客户端证书。
  • 根证书是所有后续签名的基础。

nopass:选项,表示生成的 CA 私钥不设置密码保护。

  • 如果没有 nopass,生成的私钥需要设置一个密码,每次使用时需要输入密码。

运行命令后,会在 pki 目录中生成以下文件:

  1. pki/private/ca.key:CA 的私钥文件,用于签署证书。必须妥善保管,泄露会导致整个 PKI 系统的安全性失效。
  2. pki/ca.crt:CA 的根证书,用于验证由 CA 签发的所有证书。这个文件通常会分发给客户端或服务器,用于信任链的验证。

7.1.3.3、创建服务端证书

# ./easyrsa gen-req server nopass (回车即可)

./easyrsa:这是 EasyRSA 工具的可执行脚本,用于管理私钥、证书、证书请求等。

gen-req:这个子命令用于生成证书签名请求(CSR)。它会同时生成一个私钥文件和一个与之关联的证书签名请求文件。

server:这是证书签名请求的名称(common name, CN)。生成的文件会以这个名字命名,比如:

  • 私钥:server.key
  • CSR 文件:server.req

nopass:这个选项表示生成的私钥文件不需要设置密码保护。如果没有 nopass,生成的私钥文件会要求输入密码才能使用。

7.1.3.4、签约服务端证书

[root@openvpn 3.0.6]# ./easyrsa sign server server

signEasyRSA 子命令,表示对证书签名请求(CSR)进行签名。

server:表示证书的类型。

  • server 类型的证书通常用于服务器(如 OpenVPN 服务器)。
  • EasyRSA 会根据配置为服务器证书添加相关扩展字段(如 extendedKeyUsage = serverAuth)。

server:第二个 server 是证书签名请求(CSR)的名称,与之前通过 gen-req 生成时的名称一致。

  • 它表示要签名的 CSR 文件,通常是 pki/reqs/server.req
  • 签名后的证书会被命名为 server.crt,并保存在 pki/issued/ 目录下。

7.1.3.5、创建 Diffie-Hellman

# ./easyrsa gen-dh

Diffie-Hellman (DH) 是一种密钥交换协议,用于安全生成共享密钥。

  • 在 SSL/TLS 通信中,它用于支持 Perfect Forward Secrecy (PFS),即使私钥泄露,之前的通信数据仍然无法解密。
  • 在 OpenVPN 服务器配置中,DH 参数文件是服务器端密钥交换的一部分,确保客户端与服务器之间的通信加密。

7.1.3.6、客户端证书请求

# ./easyrsa gen-req jiajia nopass

7.1.3.7、签约客户端证书

# ./easyrsa sign client jiajia

注意:这里的客户端证书用到的 pki 目录跟服务器端的 pki 目录是一样的,所以可以直接 sign 签署,如果客户端重新生成了 pki,那每次生成的证书请求文件都需要用 ./easyrsa import-req $PATH/jiajia.req jiajia 导入并取一个短名字 jiajia,然后执行 ./easyrsa sign client jiajia

参见 ./easy-rsa help import-req

7.1.3.8、生成 ta.key 文件

[root@openvpn 3.0.6]# openvpn --genkey --secret ta.key

命令 openvpn --genkey --secret ta.key 是用于生成一个预共享密钥(TA 密钥,TLS Authentication Key)。这在 OpenVPN 中主要用于增强安全性,防止未经授权的连接尝试和某些类型的攻击(如 DoS 攻击)。

--genkey:生成密钥的选项。

--secret ta.key:指定生成的密钥文件名为 ta.key

  • 这个密钥是一个对称密钥,客户端和服务器共享。
  • 文件内容是一个随机生成的 2048 位密钥。

TLS Authentication:TA 密钥用于 OpenVPN 的 TLS 认证模式。在 TLS 握手过程中,只有提供正确的 TA 密钥的客户端才会被服务器接受。

  • 防止未经授权的连接尝试。
  • 增加防火墙规则配置的灵活性。

防御攻击:TA 密钥能有效阻止某些类型的攻击。

  • 防止 DoS 攻击:通过过滤非授权数据包减轻负载。
  • 防止中间人攻击:确保握手数据的完整性。

7.1.3.9、整理证书

# pwd
/etc/openvpn/3.0.6
# ll pki/private/
-rw-------. 1 root root 1679 Jun  9 21:05 ca.key
-rw-------. 1 root root 1708 Jun  9 21:06 server.key
# ll pki/issued/
-rw-------. 1 root root 4552 Jun  9 21:18 server.crt
# ll pki/ca.crt 
-rw-------. 1 root root 1172 Jun  9 21:05 pki/ca.crt
# ll pki/dh.pem 
-rw-------. 1 root root 424 Jun  9 21:10 pki/dh.pem
# cp ta.key pki/
# ll pki/ta.key 
-rw-------. 1 root root 636 Jun  9 21:31 pki/ta.key

以上配置文件将会在服务器端和端户端配置文件中指出。

7.1.4、服务器端配置文件

# grep -vE "^#|^$" /etc/openvpn/server.conf 
local 172.18.1.206
port 1194
proto tcp
dev tun
ca /etc/openvpn/3.0.6/pki/ca.crt
cert /etc/openvpn/3.0.6/pki/issued/server.crt
key /etc/openvpn/3.0.6/pki/private/server.key
dh /etc/openvpn/3.0.6/pki/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 172.17.0.0 255.255.0.0"
keepalive 10 120
tls-auth /etc/openvpn/3.0.6/pki/ta.key 0
cipher AES-256-CBC
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3
reneg-sec 0

# 注意,这个文件用来记录被吊销的证书,阻止被吊销的客户再次登陆
# 默认没有这个文件,必须执行 ./easyrsa gen-crl 更新生成,否则服务启不来
crl-verify /etc/openvpn/3.0.6/pki/crl.pem

7.1.5、启动 openvpn 服务

# systemctl start openvpn@server.service
# systemctl enable openvpn@server.service

7.1.6、配置 iptables 规则

为了可以让客户端访问服务器所在局域网的其它主机,需要配置如下规则

# iptables -t nat -A POSTROUTING -s 10.8.0.0/8 -j MASQUERADE
# echo "1" > /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv4/ip_forward
1

7.1.7、客户端的配置文件

client
dev tun
proto tcp
remote 36.158.226.1 16001
resolv-retry infinite
persist-key
persist-tun
mute-replay-warnings
ca ca.crt
cert yll.crt
key yll.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3
mute 20
reneg-sec 0

7.1.8、生成客户端证书脚本

#!/bin/bash

install_expect() {
    if ! rpm -q expect &>/dev/null; then
        yum install expect -y
        if ! [ $? -eq 0 ]; then
            echo "Error: you must install expect manually!"
            exit -1
        fi
    fi
}

validate_input() {
    if [ $# -ne 1 ]; then
        echo "Usage: $0 USER_NAME"
        echo "-1"
        exit -1
    fi

    if ! [[ $1 =~ ^[a-zA-Z0-9_]{3,16}$ ]]; then
        echo "请使用字母数字或下划线开头的3到16个字符的名字"
        echo "-1"
        exit -1
    fi
}

check_existing_user() {
    local username=$1
    cd $dir
    if ./easyrsa show-cert "$username" &>/dev/null; then
        echo "此用户已存在,请重新输入"
        echo "-1"
        exit -1
    fi
}

generate_cert_request() {
    local username=$1
    expect <<-EOF
    spawn ./easyrsa gen-req $username nopass
    expect {
        "$username" { send "\n" }
    }
    expect eof
EOF
}

sign_cert_request() {
    local username=$1
    ./easyrsa import-req "$dir/pki/reqs/${username}.req" "$username"
    expect <<-EOF
    spawn ./easyrsa sign client $username
    expect {
        "Confirm" { send "yes\n" }
    }
    expect eof
EOF
}

prepare_client_cert_directory() {
    local username=$1
    if [ -d "/client.certs/$username" ]; then
        rm -rf "/client.certs/$username"
    fi
    mkdir -p "/client.certs/$username"
}

create_client_ovpn_template() {
    cat > /client.certs/clientsample.ovpn <<-EOF
    client
    dev tun
    proto tcp
    remote 61.187.64.38 11940
    resolv-retry infinite
    persist-key
    persist-tun
    mute-replay-warnings
    ca ca.crt
    cert sample.crt
    key sample.key
    remote-cert-tls server
    tls-auth ta.key 1
    cipher AES-256-CBC
    comp-lzo
    verb 3
    mute 20
    reneg-sec 0
EOF
}

finalize_client_ovpn() {
    local username=$1
    cd /client.certs
    cp clientsample.ovpn client.ovpn
    sed -i "s@sample.crt@${username}.crt@g" client.ovpn
    sed -i "s@sample.key@${username}.key@g" client.ovpn
    mv client.ovpn "$username/"
}

copy_cert_files() {
    local username=$1
    cp "$dir/pki/ca.crt" "/client.certs/$username"
    cp "$dir/pki/ta.key" "/client.certs/$username"
    cp "$dir/pki/issued/${username}.crt" "/client.certs/$username"
    cp "$dir/pki/private/${username}.key" "/client.certs/$username"
}

# Main script execution
install_expect

dir=/etc/openvpn/3.0.6
validate_input "$@"
check_existing_user "$1"

generate_cert_request "$1"
sign_cert_request "$1"

if ! [ -d /client.certs/ ]; then
    mkdir /client.certs/
fi

create_client_ovpn_template
prepare_client_cert_directory "$1"
copy_cert_files "$1"
finalize_client_ovpn "$1"

echo "用户 $1 的 OpenVPN 证书已生成!"

7.1.9、吊销客户端证书脚本

#!/bin/bash

validate_input() {
    if [ $# -ne 1 ]; then
        echo "Usage: $0 USER_NAME"
        echo "-1"
        exit -1
    fi

    if ! [[ $1 =~ ^[a-zA-Z0-9_]{3,16}$ ]]; then
        echo "请使用字母数字或下划线开头的3到16个字符的名字"
        echo "-1"
        exit -1
    fi
}

check_user_existence() {
    local username=$1
    cd $dir
    if ! ./easyrsa show-cert "$username" &>/dev/null; then
        echo "没有这个用户,无法删除"
        echo "-1"
        exit -1
    fi
}

revoke_certificate() {
    local username=$1
    expect <<-EOF
    spawn ./easyrsa revoke $username
    expect {
        "revocation" { send "yes\n" }
    }
    expect eof
EOF
    ./easyrsa gen-crl
}

delete_user_directory() {
    local username=$1
    rm -rf "/client.certs/$username"
}

# Main script execution
dir=/etc/openvpn/3.0.6

validate_input "$@"
check_user_existence "$1"
revoke_certificate "$1"
delete_user_directory "$1"

echo "用户 $1 的证书已被成功吊销并删除。"

7.2、openssh

7.2.1、本地端口转发

场景:我们需要远程使用 telnet 协议连接到某个被防火墙保护的内部网络中去。

local

SSH 的本地端口转发的格式如下:

ssh -L local_port:remote_host:remote_host_port sshserver

本地端口转发有如下常用选项:

  • -f:将 SSH 客户端放到后台运行,保持连接但不阻塞终端。
  • -N:只建立端口转发,而不打开远程 shell 或执行命令。单独使用 -N 会阻塞终端(除非与 -f 一起使用)。
  • -g:启用网关功能,允许非本地主机通过 SSH 客户端的本地端口发起连接,

我们的实现如下所示。 这个过程是在外部主机(172.18.253.127)上进行操作:

ssh -L 9527:172.18.253.58:23 -Nf 172.18.250.114

通过本地监听端口,使用 telnet 协议就可以访问到内部的数据库服务器了:

telnet 127.0.0.1 9527

7.2.2、远程端口转发

场景:外部主机不能访问内部主机,但内部主机可以访问外部主机,实现外部主机访问内部数据库。

remote

SSH 远程端口转发的格式如下:

ssh -R sshserver_port:remote_host:remotehost_port sshserver

我们的实现如下所示。 这个过程是在内部主机(172.18.250.114)上进行的操作:

ssh -R 9527:172.18.253.58:25 -Nf 172.18.253.127

此时我们切换到外部主机(172.18.253.127),使用 ss -tnlpu 查看一下当前监听的端口,就会发现开启了 9527 端口。如果此时我们使用 telnet 命令连接一下本地的端口,就能够像 SMTP 服务器发起 SMTP 请求了。

telnet 127.0.0.1 9527 

7.2.3、动态端口转发

场景:我们在防火墙内部想要访问放火墙外面的网站,但是防火墙给我们开放了很少的端口。如何不受限制访问外面。

dynamic

SSH 动态端口转发的格式如下:

# ssh server 指的就是我们在放火墙之外的代理服务器
# 1080 也可以是其他可用端口
ssh -D 1080 root@sshserver

我们为墙内的主机设置一下动态代理,执行这条命令的是172.18.253.127

ssh -D 1080 root@172.18.250.114

这时通过动态转发,可以将墙内主机发起的请求,转发到墙外主机,而由墙外主机去真正地发起请求。而在墙内发起的请求,需要由 Socket 代理(Socket Proxy)转发到 SSH 绑定的 1080 端口。我们以火狐浏览器为例,配置本地的网络访问代理。找到设置 => 高级 => 网络 => 代理,然后设置成如下的内容。

firefox_proxy

这样的话,Firefox 浏览器发起的请求都会转发到 1080 端口,然后通过 SSH 转发到真正的请求地址。

7.2.4、ssh 基于密钥登陆

ssh 连接大家经常用,也很好用,没有太在意,后来用到 CentOS8,openEuler24.03,KylinV10 时经常出问题,基于密钥无法认证。这里梳理一下 ssh 的认证,以及该注意的事项。

SSH 连接的主要流程:

  1. 连接建立与协商(握手阶段)
    服务器与客户端通过非对称密钥协商生成对称密钥,并商定加密、认证算法。
  2. 用户认证(认证阶段)
    客户端用非对称密钥或密码进行认证,服务器验证合法性。
  3. 数据传输(传输阶段)
    双方使用协商好的对称密钥加密数据,同时通过消息认证码(MAC)校验数据完整性。

1、握手阶段

Protocol 2

仅支持 SSH 协议版本 2(v2)。

  • SSH v1 存在严重漏洞(例如明文密钥交换)。

  • SSH v2 支持强加密(如 Diffie-Hellman、ECC)。

  • 握手阶段,双方协商协议版本。如果客户端试图使用 v1,会被拒绝连接。

  • 此配置决定了后续密钥交换算法 (KexAlgorithms)、加密算法 (Ciphers)、认证方式 (PubkeyAuthentication) 是否适用。

KexAlgorithms curve25519-sha256, diffie-hellman-group-exchange-sha256

指定密钥交换算法,生成对称密钥。

  • curve25519-sha256:使用椭圆曲线 Diffie-Hellman(ECDH)交换密钥,速度快且安全性高。

  • diffie-hellman-group-exchange-sha256:传统 Diffie-Hellman,但使用 SHA-256 防止弱散列攻击。

  • 握手阶段,双方协商使用的密钥交换算法。

  • 客户端提议 curve25519-sha256,服务器接受,双方利用此算法生成对称密钥 K。

  • 密钥交换算法直接影响后续的加密算法 (Ciphers) 和认证过程。

    • 对称加密密钥:密钥交换后,生成的对称密钥将用于数据加密。
    • 安全性影响:如果使用弱密钥交换算法(如 diffie-hellman-group1-sha1),可能被中间人攻击。

Ciphers aes128-ctr,aes256-gcm@openssh.com

  • 指定用于数据加密的对称算法,算法中是用对称密钥 K 去加密数据。
    • 依赖密钥交换算法 (KexAlgorithms) 提供的对称密钥 K。
    • 与完整性保护参数 (MACs) 协同防止数据篡改。

MACs hmac-sha2-256,hmac-sha2-512

指定消息认证码(MAC)算法,用于校验数据完整性。

  • hmac-sha2-256:SHA-256 HMAC 算法,验证数据是否被篡改。

  • hmac-sha2-512:更强的完整性保护。

  • 每个加密的数据包都附带 MAC 值,接收方根据密钥重新计算并对比,确认数据完整性。

    • Ciphers 配合使用,加密后的数据需附加 MAC。
    • 如果选择 aes256-gcm,其 GCM 模式内置完整性保护,MACs 参数可能被忽略。

2、用户认证阶段

PubkeyAuthentication yes

启用基于非对称密钥的公钥认证。

  • 客户端用私钥签名,服务器用对应公钥验证签名。
  1. 客户端发送公钥到服务器。
  2. 服务器验证公钥是否在 ~/.ssh/authorized_keys 中。
  3. 服务器发送随机数据,要求客户端用私钥签名。
  4. 服务器用公钥验证签名,确认用户身份。
  • 配合 PubkeyAcceptedKeyTypes 限制可用密钥类型(如 ssh-ed25519)。
  • 强烈建议禁用密码认证(PasswordAuthentication no),仅使用公钥认证。

PubkeyAcceptedKeyTypes ssh-ed25519,rsa-sha2-256

  • 指定允许的公钥类型。
    • ssh-ed25519:基于椭圆曲线 Ed25519 的公钥算法,速度快,安全性高。
    • rsa-sha2-256:RSA 公钥算法,使用 SHA-256 散列。
  • 服务器检查客户端提交的公钥类型是否符合配置,若不支持客户端的公钥类型,认证会失败。

StrictModes yes

  • 启用严格权限检查,防止权限过宽导致安全漏洞。
  • 用户登录前,服务器检查以下文件的权限:
    • ~/.ssh 必须为 700。
    • ~/.ssh/authorized_keys 必须为 600。

IgnoreRhosts yes

  • 禁用基于 ~/.rhosts/etc/hosts.equiv 文件的认证方式。
  • 需要配合 HostbasedAuthentication no 使用,因为 HostbasedAuthentication 依赖于 rhosts

HostbasedAuthentication no

  • 禁用主机认证(Host-based Authentication)。这种认证方式允许通过主机的私钥来认证用户,但需要客户端和服务器有匹配的主机密钥和可信设置。
  • IgnoreRhosts yes 联动。如果 HostbasedAuthentication 被禁用,~/.rhosts/etc/hosts.equiv 文件就没有作用。
  • 使用更安全的 PubkeyAuthentication 替代。

HostbasedAcceptedKeytypes

  • 定义允许用于主机认证(Host-based Authentication)的公钥算法。
  • 默认值通常包括较安全的算法,如 ssh-ed25519rsa-sha2-512
  • 认证阶段如果启用了 HostbasedAuthentication,服务器会验证这些算法生成的签名。
  • 如果 HostbasedAuthentication no,此参数将被忽略。

PermitUserEnvironment no

  • 禁止通过 .ssh/environment 文件设置环境变量。

  • 防止攻击者利用恶意环境变量干扰会话行为。

  • 登录阶段如果启用了用户环境配置,服务器会读取 ~/.ssh/environment 文件并应用其中的变量。

AllowTcpForwarding no

  • 禁止 SSH 会话中的 TCP 转发功能。
  • 这意味着客户端不能通过服务器建立额外的 TCP 通道。
  • 会话阶段防止用户在已登录的会话中转发流量到其他目标主机。
  • 可配合 AllowAgentForwarding no 使用,彻底防止用户滥用会话隧道功能。

AllowAgentForwarding no

  • 禁止客户端通过 SSH 代理转发认证请求。

GatewayPorts no

  • 禁止远程端口转发对外开放端口。
  • 即便开启了端口转发,转发的端口只能监听 localhost,不能对外提供服务。
  • 配合 AllowTcpForwarding no 可完全关闭所有转发功能。

PermitTunnel no

  • 禁止通过 SSH 创建网络隧道(Layer 2 或 Layer 3)。
  • 防止用户利用隧道访问内部网络资源。
  • 同样是限制 SSH 会话能力的参数,配合 AllowTcpForwarding no 提高安全性。

GSSAPIKexAlgorithms

  • 定义支持的 GSSAPI 密钥交换算法。

  • 用于 Kerberos 或其他基于 GSSAPI 的认证协议。

  • 密钥交换阶段,当客户端和服务器都支持 GSSAPI 时,可以协商使用这些算法进行密钥交换。

  • 如果服务器启用了 GSSAPIAuthentication yes,会使用此参数指定支持的 GSSAPI 算法。

  • 常见于需要 Kerberos 集成的环境。

CASignatureAlgorithms

  • 定义允许使用的 CA 签名算法。
  • SSH 可以通过 CA 签名的公钥进行认证,此参数限制支持的 CA 签名类型。
  • 认证阶段,验证客户端或服务器的公钥是否被允许的 CA 签名。
  • PubkeyAcceptedKeyTypesHostKeyAlgorithms 结合,用于限制公钥的类型和 CA 签名。

HostKeyAlgorithms

  • 定义服务器支持的主机密钥算法。
  • 主机密钥用于验证服务器的身份。
  • 认证阶段,客户端验证服务器提供的主机密钥是否匹配信任列表。
  • PubkeyAcceptedKeyTypes 相辅相成,分别限制客户端和服务器的密钥类型。
  • 建议仅使用现代算法(如 ssh-ed25519rsa-sha2-512)。

3、数据传输阶段

ClientAliveCountMax 0ClientAliveInterval

控制客户端的空闲连接行为。

  • ClientAliveInterval:服务器向客户端发送心跳包的间隔(秒)。
  • ClientAliveCountMax:客户端未响应心跳包后允许的最大次数。
    • 每隔 ClientAliveInterval 秒,服务器发送心跳包。如果客户端无响应,断开连接。
    • 设置为 0 表示立即断开连接。

注意:如果基于密钥认证出现所选的用户密钥未在远程主机上注册,一般是目录和文件权限问题,或者是两边算法不匹配,那就好好理解上面的参数含义。

7.3、frp

官方仓库:https://github.com/fatedier/frp

官方文档:https://gofrp.org/zh-cn/docs/

frp 是什么?

frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。

为什么选择 frp?

通过在具有公网 IP 的节点上部署 frp 服务端,您可以轻松地将内网服务穿透到公网,并享受以下专业特性:

  • 多种协议支持:客户端服务端通信支持 TCP、QUIC、KCP 和 Websocket 等多种协议。
  • TCP 连接流式复用:在单个连接上承载多个请求,减少连接建立时间,降低请求延迟。
  • 代理组间的负载均衡。
  • 端口复用:多个服务可以通过同一个服务端端口暴露。
  • P2P 通信:流量不必经过服务器中转,充分利用带宽资源。
  • 客户端插件:提供多个原生支持的客户端插件,如静态文件查看、HTTPS/HTTP 协议转换、HTTP、SOCKS5 代理等,以便满足各种需求。
  • 服务端插件系统:高度可扩展的服务端插件系统,便于根据自身需求进行功能扩展。
  • 用户友好的 UI 页面:提供服务端和客户端的用户界面,使配置和监控变得更加方便。

官方示例够用了 https://gofrp.org/zh-cn/docs/examples/

通过简单配置 TCP 类型的代理,使用户能够访问内网服务器。

步骤

  1. 在具有公网 IP 的机器上部署 frps

    部署 frps 并编辑 frps.toml 文件。以下是简化的配置,其中设置了 frp 服务器用于接收客户端连接的端口:

    bindPort = 7000
  2. 在需要被访问的内网机器上部署 frpc

    部署 frpc 并编辑 frpc.toml 文件,假设 frps 所在服务器的公网 IP 地址为 x.x.x.x。以下是示例配置:

    serverAddr = "x.x.x.x"
    serverPort = 7000
    
    [[proxies]]
    name = "ssh"
    type = "tcp"
    localIP = "127.0.0.1"
    localPort = 22
    remotePort = 6000
    • localIPlocalPort 配置为需要从公网访问的内网服务的地址和端口。
    • remotePort 表示在 frp 服务端监听的端口,访问此端口的流量将被转发到本地服务的相应端口。
      • 注意,仅启动 frps 服务端是没有 remotePort 端口监听的,只有 frpc 客户端启动,连接 frps 服务端时,remotePort 端口才会送到服务端,服务端开始监听该端口。
  3. 启动 frps 和 frpc

  4. 通过 SSH 访问内网机器

    使用以下命令通过 SSH 访问内网机器,假设用户名为 test:

    ssh -o Port=6000 test@x.x.x.x

    frp 将请求发送到 x.x.x.x:6000 的流量转发到内网机器的 22 端口。

官方仓库有完整的配置参考 https://github.com/fatedier/frp/tree/dev/conf ,当然官方文档也有详细说明,一般从完整配置中取一部分也就够用了。

标签云