Security Frp & SSH
关于如何配置我认为比较安全的 Frp反向代理 并通过 ssh 远程连接环境。
前言
现在我的的开发环境更多的是使用一种「Thin Client」的方式,指将更多的开发环境放置需要被远程连接的机器,而前端的计算机则通过连接服务器进行开发。
具体环境就是在工作中笔记本作为前端提供 ssh 连接服务器的能力,而后端的服务器提供服务,并具备包括编辑环境、编译环境的能力。
更换笔记本以后,旧的本身就已经是使用的 Arch Linux 发行版,所以非常适合这种方式。但这就引入了另一个问题,我该如何将这种方式带到任何地点而非仅仅是局域网。
概览
如上图,拥有公网 IP 的 Cloud Server 不仅对外提供各种服务同时作为 frp server 端对需要的内网机器提供反向代理的能力。为了保证建立连接时的可靠性,在 FRP 间采用 TLS 双向认证的策略,在 ssh 连接设置上关闭密码验证,而是采用 authorized_keys 管理客户端公钥的方式进行连接认证。
Frp
关于概念就不过多介绍了,主要功能就是反向代理的应用,支持多种协议,并且还支持连接的 TLS 双向认证,安全地将搭建在内网的服务暴露到公网。
证书与密钥生成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| cat > my-openssl.cnf << EOF [ ca ] default_ca = CA_default [ CA_default ] x509_extensions = usr_cert [ req ] default_bits = 2048 default_md = sha256 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca string_mask = utf8only [ req_distinguished_name ] [ req_attributes ] [ usr_cert ] basicConstraints = CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer [ v3_ca ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = CA:true EOF
|
1 2
| openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt
|
1 2 3 4 5 6 7 8 9 10 11 12
| openssl genrsa -out server.key 4096
openssl req -new -sha256 -key server.key \ -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \ -reqexts SAN \ -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \ -out server.csr
openssl x509 -req -days 365 -sha256 \ -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \ -out server.crt
|
此处的 IP 需要使用实际的公网 IP 地址。
1 2 3 4 5 6 7 8 9 10 11
| openssl genrsa -out client.key 4096 openssl req -new -sha256 -key client.key \ -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \ -reqexts SAN \ -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \ -out client.csr
openssl x509 -req -days 365 -sha256 \ -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \ -out client.crt
|
frp 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| vim /etc/frp/conf/frpc.ini """ [common] bind_prt = 7000 bind_addr = 0.0.0.0 dashboard_port = 7500 dashboard_user = 用户名 dashboard_pwd = password # 用于登陆 dashboard
tls_enable = true tls_verify_client = true tls_trusted_ca_file = /etc/frp/ssl/ca.crt tls_cert_file = /etc/frp/ssl/server.crt tls_key_file = /etc/frp/ssl/server.key
allow_ports = 6000-6010 """
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| vim /etc/frp/conf/frpc.ini """ [common] server_addr = 公网 IP server_port = 7000
tls_enable = true tls_cert_file = /etc/frp/ssl/client.crt tls_key_file = /etc/frp/ssl/client.key tls_trusted_ca_file = /etc/frp/ssl/ca.crt tls_server_name = # 公网 IP 或 域名,取决于证书时的 SAN 内容
[ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 6001 """
|
配置文件的目的主要是指定本地的双向认证的证书与密钥文件,包括将 frpc 的 22 端口映射到 frps 的 6001 端口。
注:.ini的配置文件格式在未来可能弃用,建议采用 yaml 或 toml 格式
Systemd 管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| vim /etc/systemd/system/frpc.service """ [Unit] Description=FRP Server Daemon After=network.target
[Service] Type=simple WorkingDirectory=/etc/frp ExecStart=/usr/local/bin/frpc -c /etc/frp/conf/frpc.ini Restart=always RestartSec=5
# security PrivateTmp=true ProtectSystem=full ProtectHome=true ReadOnlyDirectories=/ ReadWriteDirectories=/etc/frp NoNewPrivileges=true
[Install] WantedBy=multi-user.target """ sudo systemctl enable frpc.service sudo systemctl start frpc.service
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| vim /etc/systemd/system/frps.service """ [Unit] Description=FRP Server Daemon After=network.target
[Service] Type=simple WorkingDirectory=/etc/frp ExecStart=/usr/local/bin/frps -c /etc/frp/conf/frps.ini Restart=always RestartSec=5
PrivateTmp=true ProtectSystem=full ProtectHome=true ReadOnlyDirectories=/ ReadWriteDirectories=/etc/frp NoNewPrivileges=true CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install] WantedBy=multi-user.target """ sudo systemctl enable frps.service sudo systemctl start frps.service
|
SSH
ssh 的配置主要是针对于内网提供 ssh 服务的机器,尽可能更多的限制连接的条件,我能想到的就是只使用主动添加到 authorized_keys 中保存的机器公钥。
1 2 3 4 5
| vim /etc/ssl/sshd.conf
PasswordAuthentication no PubkeyAuthentication yes AuthorizedKeysFile ~/.ssh/authorized_keys
|
1 2
| ssh-keygen -t en25519 -C "example@mail.com" cat ~/.ssh/id_ed25519.pub
|
将公钥的内容放置 ssh 服务端的需要被使用的用户的 ~/.ssh/authorized_keys 中。
连接
1
| ssh -p 6001 user_name@xxx.xxx.xxx.xxx
|
ssh连接公网IP指定端口和用户名即可。
参考