Zhonghui

每个不曾起舞的日子,都是对生命的辜负

User Tools

Site Tools


软件:linux:apache反向代理

Apache 反向代理

服务器程序在3000端口提供服务,没有向外暴露;Apache 2绑定80端口,向外提供服务
Apache 2把接收到的请求转发给真正的服务器程序处理,这就是反向代理


步骤

  1. 启用模块proxyproxy_httpApache模块
  2. 编辑配置文件(参考下述代码)
  3. 启动真的服务器
  4. 重启 Apache 2

反向代理配置

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    # 这个路径应该不需要配置吧
    DocumentRoot /var/www/html

    # 反向代理配置
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

反向代理 & HTTPS

https://github.com/GZhonghui/Web101/tree/master/04_https

Node 端 server.js

// 需要开启信任代理
// 当使用反向代理时,实际的客户端 IP 地址会被代理服务器(Apache2)的 IP 地址替代
// 设置 trust proxy 后,Express 会信任代理服务器传递的 HTTP 头(如 X-Forwarded-For, X-Forwarded-Proto 等)
// 从而可以获取到真实的客户端 IP 地址
app.set('trust proxy', true);
 
...
 
// 绑定地址和端口的时候,使用 localhost:<非常用端口> 即可
const PORT = 3001;
 
app.listen(PORT, 'localhost', () => {
    console.log(`server is running on http://localhost:${PORT}`);
});
 
...
 
// 其他代码保持不变即可

Apache 端

在后台启动 node 服务器

启用 Apache 所需模块

# 启用 SSL 和代理模块
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo a2enmod remoteip
sudo service apache2 reload

开启 HTTP 服务 并绑定域名

<VirtualHost *:80>
    ServerName domain.com # 绑定域名
    ServerAdmin webmaster@localhost

    # 反向代理配置
    ProxyPreserveHost On
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

# 配置好之后重启 Apache
sudo service apache2 restart

现在应该可以从外部使用域名访问到 node 服务器了 如果不行 请等待 DNS 解析或者清空浏览器缓存、使用无痕模式尝试

安装 acme.sh 并申请证书 这里我们使用非 root 身份(但是有 sudo 权限)

# 安装 acme.sh
cd
curl https://get.acme.sh | sh -s email=my@example.com
source ~/.bashrc
acme.sh --help
 
# 申请证书
# 域名是我们在 Apache 配置中绑定的域名
# 网站根目录是我们反向代理服务器的 public 目录
acme.sh --issue -d domain.com -w /home/ubuntu/Web101/04_https/public/
 
# 安装证书
acme.sh --install-cert -d domain.com \
--cert-file      /home/ubuntu/Web101/04_https/cert/cert.pem  \
--key-file       /home/ubuntu/Web101/04_https/cert/key.pem  \
--fullchain-file /home/ubuntu/Web101/04_https/cert/fullchain.pem \
--reloadcmd     "sudo service apache2 force-reload" # 因为不是 root 用户 所以需要使用 sudo 权限

完成之后 在 Apache 配置中启用 HTTPS 服务

# HTTP 虚拟主机配置 (/etc/apache2/sites-available/your-site.conf)
<VirtualHost *:80>
    ServerName domain.com
    ServerAdmin webmaster@localhost

    # 重定向所有 HTTP 流量到 HTTPS
    # 直接重定向到首页 这种做法比较简单
    Redirect permanent / https://domain.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName domain.com
    
    # 启用 SSL
    # fullchain.pem 是证书链文件 如果需要的话就加上
    SSLEngine on
    SSLCertificateFile /home/ubuntu/Web101/04_https/cert/cert.pem
    SSLCertificateKeyFile /home/ubuntu/Web101/04_https/cert/key.pem
    SSLCertificateChainFile /home/ubuntu/Web101/04_https/cert/fullchain.pem
    
    # 启用代理
    ProxyPreserveHost On
    
    # 添加请求头转发
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-SSL "on"
    
    # 转发真实的客户端IP
    ProxyAddHeaders On
    RemoteIPHeader X-Forwarded-For
    
    # 反向代理配置
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

# 配置好之后重启 Apache
# 如果 Apache 重启失败 可能是部分模块没有启用 请检查 /etc/apache2/mods-enabled
sudo service apache2 restart

最后 检查一下 acme.sh 的 list,另外因为开启了 HTTPS 所以也要检查一下服务器的 443 端口是否开启。一切正常之后 就可以使用域名访问到 node 服务器了

反向代理 & HTTPS & Apache 2验证证书

如果服务程序是我们自己运行的,还算能找到真正的 public_path / web_root 在哪里,但是也有很多情况我们不知道这个目录在哪里,所以最好不要依赖与用这个目录验证证书
以下,我们在服务器上运行一个服务程序(以Alist为例),考虑使用Apache 2进行反向代理,并开启HTTPS
全程使用 root 身份

1 开启 Alist 服务,在 http://localhost:xxxx/ 提供服务,其余信息不需要
2 安装 acme.sh
3 启用 Apache 2 的模块(rewrite, alias, ssl, proxy, proxy_http, headers, remoteip 使用 a2enmod 命令)
4 配置 Apache 2 的HTTP

<VirtualHost *:80>
    ServerName yourdomain.com

    # 让 ACME 验证的请求能访问本地某个目录 (如 /var/www/certroot)
    # 注意要提前创建好 /var/www/certroot 这个目录 我们用于验证证书
    DocumentRoot /var/www/certroot
    <Directory /var/www/certroot>
        Require all granted
    </Directory>
    
    # 如果访问的路径是 .well-known/acme-challenge 下的文件,就让它直接访问本地
    # 否则全部重定向到 HTTPS
    RewriteEngine On
    
    # 如果 URL 不匹配 .well-known/acme-challenge/,则跳转到 HTTPS
    RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
    RewriteRule ^/(.*) https://yourdomain.com/$1 [R=301,L]
</VirtualHost>

5 重启服务器,我们验证配置,做申请证书前的准备

# 创建一个验证文件
root@NY-1:/var/www/certroot/.well-known/acme-challenge# pwd
/var/www/certroot/.well-known/acme-challenge
root@NY-1:/var/www/certroot/.well-known/acme-challenge# ls
test.txt

# 尝试使用 HTTP 访问 能访问到则成功
http://yourdomain.com/.well-known/acme-challenge/test.txt

# 测试完之后记得把 test.txt 删了

6 申请证书

acme.sh --issue -d yourdomain.com -w /var/www/certroot

7 安装证书

acme.sh --install-cert -d yourdomain.com \
--cert-file      /root/cert/yourdomain.com/cert.pem  \
--key-file       /root/cert/yourdomain.com/key.pem  \
--fullchain-file /root/cert/yourdomain.com/fullchain.pem \
--reloadcmd     "service apache2 force-reload"

8 有证书之后,我们补充 Apache 2 的 HTTPS 配置

<VirtualHost *:443>
    ServerName yourdomain.com
    
    # 启用 SSL
    # fullchain.pem 是证书链文件 如果需要的话就加上
    SSLEngine on
    SSLCertificateFile /root/cert/yourdomain.com/cert.pem
    SSLCertificateKeyFile /root/cert/yourdomain.com/key.pem
    SSLCertificateChainFile /root/cert/yourdomain.com/fullchain.pem
    
    # 启用代理
    ProxyPreserveHost On
    # 用于禁止正向代理,一般在做反向代理时为了安全都会配置
    ProxyRequests Off
    
    # 允许请求 URL 里带 %2F,并且不把它解码成 /,让后端自己解析 (Alist 要求)
    AllowEncodedSlashes NoDecode
    
    # 添加请求头转发
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-SSL "on"
    
    # 转发真实的客户端IP
    ProxyAddHeaders On
    RemoteIPHeader X-Forwarded-For
    
    # 反向代理配置
    # nocanon 表示:禁止 Apache 对代理请求的路径做额外的“规范化”或“编码处理”
    # 把原始请求尽可能忠实地传给后端 (Alist 要求)
    ProxyPass "/" "http://127.0.0.1:5244/" nocanon
    ProxyPassReverse "/" "http://127.0.0.1:5244/" nocanon
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
/var/www/DokuWikiStick/dokuwiki/data/pages/软件/linux/apache反向代理.txt · Last modified: 2025/02/24 17:02 by zhonghui