本文记录 Fedora 部署 Frp 服务端,使用自签名证书与 Alpine 部署的 Frp 客户端通信。并配置 Nginx 前置代理,Cerbot 申请 SSL 证书。
Fedora 部署 Frp 服务端
安装 Frps
打开 Frp 项目releases主页,查看最新 Release 版本。
下载 frp,假设最新版本是 0.51.3 。
export FRPVER=0.51.3
wget https://github.com/fatedier/frp/releases/download/v$FRPVER/frp_$FRPVER\_linux_amd64.tar.gz
tar -zxvf frp_$FRPVER\_linux_amd64.tar.gz
cd frp_$FRPVER\_linux_amd64
sudo cp frps /usr/bin
sudo mkdir /etc/frp && sudo cp frps.toml /etc/frp
sudo chmod 600 -R /etc/frp
cd ..
添加 frps 服务到 systemd 。
sudo cat > /etc/systemd/system/frps.service <<EOF
[Unit]
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
ExecStart = /usr/bin/frps -c /etc/frp/frps.toml
Restart = on-failure
[Install]
WantedBy = multi-user.target
EOF
生成证书
生成自签名证书,假设域名:example.com,IP地址:1.2.3.4。
# 修改域名和IP
export DOMAIN=example.com
export IPADDR=1.2.3.4
# 生成根 CA 密钥
openssl ecparam -out ca.key -name prime256v1 -genkey
# 生成根 CA CSR
openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=$DOMAIN Inc/OU=$DOMAIN/CN=$DOMAIN/emailAddress=admin@$DOMAIN"
# 生成根 CA 证书
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 3650
# 生成 frp 密钥
openssl ecparam -out frp.key -name prime256v1 -genkey
# 生成 frp CSR
openssl req -new -key frp.key -out frp.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=$DOMAIN Inc/OU=$DOMAIN/CN=$DOMAIN/emailAddress=admin@$DOMAIN"
# 生成 frp 证书)
openssl x509 -req -extfile <(printf "subjectAltName=IP:$IPADDR") -in frp.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out frp.crt -days 3650
# 查看 frp 证书信息
openssl x509 -in frp.crt -noout -text
# 复制到 frp 配置目录
sudo mkdir /etc/frp/tls
sudo cp frp.{crt,key} /etc/frp/tls/
sudo cp ca.crt /etc/frp/tls/
配置 Frps
配置 frps.toml 。修改想要绑定的端口,密码 passwd 。在防火墙开放对应端口。
sudo cat > /etc/frp/frps.toml <<EOF
bindAddr = "0.0.0.0"
bindPort = 7000
kcpBindPort = 7002
quicBindPort = 7003
transport.tls.force = true
transport.tls.certFile = "/etc/frp/tls/frp.crt"
transport.tls.keyFile = "/etc/frp/tls/frp.key"
transport.tls.trustedCaFile = "/etc/frp/tls/ca.crt"
log.to = "/var/log/frps.log"
log.level = "warn"
log.maxDays = 3
auth.method = "token"
auth.token = "passwd"
EOF
配置 sysctl ,传输 quic 需要。
sudo cat > /etc/sysctl.d/99-frp.conf <<EOF
net.core.rmem_max=2500000
net.core.wmem_max=2500000
EOF
sysctl -p /etc/sysctl.d/99-frp.conf
启动 frps。
sudo systemctl start frps
sudo systemctl status frps
# 设置开机启动
sudo systemctl enable frps
Alpine 安装 Frp 客户端
安装和开启 SSH 。(可选)
apk update
apk add openssh
service sshd start
rc-update add sshd
安装 Frp
Alpine 包源有 Frp ,直接安装。
apk add frp
配置 Frpc
复制服务端的 frp.crt,frp.key,ca.crt 上传到 /etc/frp/tls 。
配置 frpc.toml 。假设服务器IP:0.0.0.0,端口:7003,使用协议:quic ,密码:passwd 。
cat > /etc/frp/frpc.toml <<EOF
user = "home"
serverAddr = "0.0.0.0"
serverPort = 7003
loginFailExit = false
log.to = "/var/log/frpc.log"
log.level = "warn"
log.maxDays = 3
auth.method = "token"
auth.token = "passwd"
transport.protocol = "quic"
transport.tls.enable = true
transport.tls.certFile = "/etc/frp/tls/frp.crt"
transport.tls.keyFile = "/etc/frp/tls/frp.key"
transport.tls.trustedCaFile = "/etc/frp/tls/ca.crt"
EOF
配置 sysctl 。
cat > /etc/sysctl.d/99-frp.conf <<EOF
net.core.rmem_max=2500000
net.core.wmem_max=2500000
EOF
sysctl -p /etc/sysctl.d/99-frp.conf
启动 frpc。
service frpc start
rc-update add frpc
Nginx 前置代理 Frps
使用 Nginx 作为 frps 的前置代理。
修改 frps 配置监听 HTTP,注意防火墙不开放此端口。
vhostHTTPPort = 7080
安装 Nginx。
sudo dnf install nginx
Cerbot 申请 SSL 证书
sudo dnf install certbot python3-certbot-dns-cloudflare
创建一个 CloudFlare 编辑DNS 的 Token,写入配置文件。
sudo cat > /etc/letsencrypt/cloudflare.ini <<EOF
dns_cloudflare_api_token = _yourToken_
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
申请证书。
export DOMAIN=example.com
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
--key-type ecdsa \
--domain "$DOMAIN,*.$DOMAIN"
配置 Cerbot 自动续签证书。
sudo cat > /etc/systemd/system/certbot.service <<EOF
[Unit]
Description=Let's Encrypt renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
EOF
cat > /etc/systemd/system/certbot.timer <<EOF
[Unit]
Description=Automatic renewal of Let's Encrypt's certificates
[Timer]
OnCalendar=03:00:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl enable --now certbot.timer
配置 Nginx
生成 DH 文件。
sudo openssl dhparam -dsaparam -out /etc/ssl/private/dsa4096.pem 4096
新建 SSL 的配置文件。
sudo mkdir -p /etc/nginx/snippets/ssl
sudo cat > /etc/nginx/snippets/ssl/ssl.conf <<EOF
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384';
EOF
sudo cat > /etc/nginx/snippets/ssl/dhparam.conf <<EOF
# Path of the file with Diffie-Hellman parameters for EDH ciphers.
# TIP: Generate with: openssl dhparam -dsaparam -out /etc/ssl/private/dsa4096.pem 4096
ssl_dhparam /etc/ssl/private/dsa4096.pem;
ssl_ecdh_curve secp521r1:secp384r1;
EOF
sudo cat > /etc/nginx/snippets/ssl/ocsp.conf <<EOF
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
EOF
sudo cat > /etc/nginx/snippets/ssl_params.conf <<EOF
include snippets/ssl/ssl.conf;
include snippets/ssl/dhparam.conf;
include snippets/ssl/ocsp.conf;
EOF
准备好 SSL证书,假设证书存放目录是 /etc/letsencrypt/live/example.com 。
sudo cat > /etc/nginx/snippets/example.com_cert.conf <<EOF
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
EOF
新建 Proxy 的配置文件。
sudo mkdir -p /etc/nginx/snippets/proxy/map
sudo cat > /etc/nginx/snippets/proxy/map/connection_upgrade.conf <<EOF
map \$http_upgrade \$connection_upgrade {
default upgrade;
'' close;
}
sudo cat > /etc/nginx/snippets/proxy/buffer.conf <<EOF
proxy_buffer_size 64k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
EOF
sudo cat > /etc/nginx/snippets/proxy/header.conf <<EOF
proxy_redirect off; #重写代理服务器响应中的Location和Refresh重定向字段
proxy_ssl_server_name on; #传递主机名给代理服务器
proxy_set_header Host \$host; #设置请求头Host字段主机名
proxy_set_header X-Real-IP \$remote_addr; #设置请求头X-Real-IP字段客户端真实ip
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; #设置请求头X-Forwarded-For字段客户端真实ip+转发ip
proxy_set_header X-Forwarded-Port \$server_port;
proxy_set_header X-Forwarded-Proto \$scheme; #设置请求头X-Forwarded-Proto转发协议(https)
proxy_set_header Upgrade \$http_upgrade; #设置请求头Upgrade和Connection用于http协议升级websocket
proxy_set_header Connection \$connection_upgrade;
proxy_http_version 1.1; #代理请求http协议版本1.1
EOF
sudo cat > /etc/nginx/snippets/proxy/timeout.conf <<EOF
proxy_connect_timeout 75s; #nginx 跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 600s; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_read_timeout 600s; #请求的超时时间
EOF
sudo cat > /etc/nginx/snippets/proxy_params.conf <<EOF
include snippets/proxy/header.conf;
include snippets/proxy/buffer.conf;
include snippets/proxy/timeout.conf;
EOF
假设 Frps 监听的 http 端口是 7080。
sudo cat > /etc/nginx/snippets/frps_proxy.conf <<EOF
proxy_pass http://127.0.0.1:7080;
EOF
新建其他配置文件。
```bash
sudo cat > /etc/nginx/snippets/client_params.conf <<EOF
client_max_body_size 512M;
client_body_timeout 300s;
client_body_buffer_size 512k;
EOF
sudo cat > /etc/nginx/snippets/hsts.conf <<EOF
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
EOF
最后,新建域名的配置文件,假设域名 example.com 。
sudo cat > /etc/nginx/conf.d/example.com.conf <<EOF
include snippets/proxy/map/*.conf;
server {
listen 80;
server_name example.com;
server_name *.example.com;
rewrite ^(.*)\$ https://\$host\$1 permanent; #重定向所有非 https 请求
}
server {
listen 443 ssl http2;
server_name example.com;
server_name *.example.com;
include snippets/example.com_cert.conf;
include snippets/ssl_params.conf;
include snippets/hsts.conf;
location / {
include snippets/frps_proxy.conf;
include snippets/proxy_params.conf;
}
include snippets/client_params.conf;
}
EOF
测试 nginx 配置文件。
nginx -t
启动 nginx 。
systemctl start nginx
systemctl enable nginx