Fedora + Alpine 部署 Frp 内网穿透

本文记录 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

发表评论

目录