Rails Apache2 mod_proxy 运行一段时间后报 403 Forbidden 的错

crazyjacky · 2022年04月27日 · 最后由 crazyjacky 回复于 2022年04月28日 · 88 次阅读

具体配置如下

<Proxy balancer://cluster1>
    BalancerMember http://host1.com:3000 route=1 loadfactor=10 connectiontimeout=120 timeout=120
    BalancerMember http://host2.com:3000 route=2 loadfactor=8 connectiontimeout=120 timeout=120
    BalancerMember http://host3.com:3000 route=3 loadfactor=10 connectiontimeout=120 timeout=120
    ProxySet lbmethod=byrequests
    ProxySet stickysession=ROUTEID
</Proxy>

<VirtualHost *:80>
  Redirect permanent / https://host1.com/
  ServerName host1.com
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =host1.com
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:80>
  Redirect permanent / https://host1.com/
  ServerName www.host1.com
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =www.host1.com
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>

  ServerName host1.com
  # RewriteEngine On
  # RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

  SSLEngine on
  SSLProxyEngine on

  <IfModule headers_module>
      Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
      Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains"
      Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
  </IfModule>

  ServerAlias       host1.com
  Include    /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile  /etc/letsencrypt/live/host1.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/host1.com/privkey.pem

  ProxyRequests Off
  #ProxyPreserveHost On
  ProxyPass /server-status !
  ProxyPass / balancer://cluster1/
  ProxyPassReverse / balancer://cluster1/
</VirtualHost>

每个 host 上面通过 puma 启动 rails 服务

运行一段时间后,apache 那边就会报 403 的错。 请问这是什么问题?怎么解决?

查看了 apache log,有两个错误信息:

AH00898: Error reading from remote server returned by /xxx AH01102: error reading status line from remote server host1

Update:

AH01102 是 timeout,应该是 proxy 到 backend 超时了,因为有一个 host 的配置比较低,如果 requests 多了,cpu/memory 会用满,然后就会导致连接超时。 解决办法:增加 timeout 的时间,默认是 5 秒,改到了 60 秒。

AH00898SSL Handshake相关的错误,proxy 是 enable SSL,而 backend 没有,不知道会不会是这个原因。 https://serverfault.com/questions/538086/proxyerror-ah00898-error-during-ssl-handshake-with-remote-server 我先按照上面这个试试,再看看是否能解决问题。

问题解决

是因为我用了 rack_attack gem,同一个 ip 如果 5 分钟内请求超过 200 次,就 ban for 1 hour。 之前单机没问题,后来流量涨了,于是用了 apache2 的 mod_proxy,于是从 proxy 到 backend 服务器,backend 服务器 rack 的 request.ip 返回的是 proxy 的 ip,这样就导致了过一阵之后,proxy ip 就被 banned,以至于一直报 forbidden 的错。

google 一下之后,rack_attack 的 github 上有在讨论这个问题 https://github.com/rack/rack-attack/issues/145 于是依样画葫芦改了一下。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号