在使用 Cloudflare 时依靠 "X-Forwarded-For" 来限制 Apache 中的 IP 访问是否安全?
Is it secure to rely on "X-Forwarded-For" to restrict access by IP in Apache while using Cloudflare?
我使用这样的 .htaccess 文件将对目录的访问限制为某些 IP 地址:
AuthType Basic
AuthName "Protected"
<RequireAny>
Require ip 1.2.3.4
</RequireAny>
这在正常的服务器设置中工作正常,但是当使用 Cloudflare 作为 WAF 代理时,它停止工作,因为服务器接收通过 Cloudflare 的 IP 代理的所有请求。
作为一种解决方法,可以使用 "X-Forwarded-For" header 来识别客户端的 "real" IP 地址,因为 Cloudflare 会在其所有请求中传递此地址:
AuthType Basic
AuthName "Protected"
SetEnvIf X-Forwarded-For 1.2.3.4$ allowed
<RequireAny>
Require env allowed
</RequireAny>
这是一种安全的方法还是有一种better/more安全的方法来限制使用 Cloudflare 时 Apache 中客户端 IP 的访问?
根据IETF RFC 2616, Section 4.2, a header can hold a comma separated list of values, and this is the case of X-Forwarded-For
as Cloudflare uses it。
If an X-Forwarded-For header was already present in the request to
Cloudflare, Cloudflare appends the IP address of the HTTP proxy to the
header:
Example: X-Forwarded-For: 203.0.113.1,198.51.100.101,198.51.100.102
In the examples above, 203.0.113.1 is the original visitor IP address and
198.51.100.101 and 198.51.100.102 are proxy server IP addresses provided to Cloudflare via the X-Forwarded-For header.
习惯上取最左边的IP为真实IP,但并非总是如此。
如果你这样做,你应该检查与你的 IP 匹配的正则表达式
SetEnvIf X-Forwarded-For ^1\.2\.3\.4 allowed
(最左边的IP,转义点)
更好的方法(恕我直言)
Cloudflare 还发送 header cf-connecting-ip
(这意味着在发送到您的计算机之前最后一个访问 cloudflare 的 IP)我宁愿使用那个。
Is this a safe approach or is there a better/more secure way to limit
access by client IP in Apache when Cloudflare is being used?
有个问题。在这种情况下,您要告诉 Apache:
"we have cloudflare in the middle so instead of your native way to tell the visitor's IP let's look at this custom header".
那个习俗header是可以伪造的。绝对地。因此,你也应该说:
"this custom header should be taken as reliable if and only the request comes from a Cloudflare IP".
Cloudflare does explicitly list their IP ranges
最后,您应该使用 mod_remoteip 而不是手动构建 SetEnvIf 规则。
基本上:
# /etc/apache2/conf-enabled/remoteip.conf
RemoteIPHeader CF-Connecting-IP
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
...
RemoteIPTrustedProxy 2606:4700::/32
RemoteIPTrustedProxy 2803:f800::/32
或者,将 IP 列表放在单独的文件中:
# /etc/apache2/conf-enabled/remoteip.conf
RemoteIPHeader CF-Connecting-IP
RemoteIPTrustedProxyList conf/trusted-proxies.lst
和
# conf/trusted-proxies.lst
173.245.48.0/20
103.21.244.0/22
...
...
2803:f800::/32
2606:4700::/32
如果说 header 没有出现在请求中,Apache 回退到 ro REMOTE_ADDR。来自不受信任的 IP 的请求也是如此。如果 header 存在并且来自 Cloudflare,您只需执行以下操作:
Require ip 1.2.3.4
这种方法会在您需要使用它的任何地方(日志、身份验证等)替换 IP,并在边缘情况下优雅地退回到原始 REMOTE_ADDR。
我使用这样的 .htaccess 文件将对目录的访问限制为某些 IP 地址:
AuthType Basic
AuthName "Protected"
<RequireAny>
Require ip 1.2.3.4
</RequireAny>
这在正常的服务器设置中工作正常,但是当使用 Cloudflare 作为 WAF 代理时,它停止工作,因为服务器接收通过 Cloudflare 的 IP 代理的所有请求。
作为一种解决方法,可以使用 "X-Forwarded-For" header 来识别客户端的 "real" IP 地址,因为 Cloudflare 会在其所有请求中传递此地址:
AuthType Basic
AuthName "Protected"
SetEnvIf X-Forwarded-For 1.2.3.4$ allowed
<RequireAny>
Require env allowed
</RequireAny>
这是一种安全的方法还是有一种better/more安全的方法来限制使用 Cloudflare 时 Apache 中客户端 IP 的访问?
根据IETF RFC 2616, Section 4.2, a header can hold a comma separated list of values, and this is the case of X-Forwarded-For
as Cloudflare uses it。
If an X-Forwarded-For header was already present in the request to Cloudflare, Cloudflare appends the IP address of the HTTP proxy to the header:
Example: X-Forwarded-For: 203.0.113.1,198.51.100.101,198.51.100.102
In the examples above, 203.0.113.1 is the original visitor IP address and 198.51.100.101 and 198.51.100.102 are proxy server IP addresses provided to Cloudflare via the X-Forwarded-For header.
习惯上取最左边的IP为真实IP,但并非总是如此。
如果你这样做,你应该检查与你的 IP 匹配的正则表达式
SetEnvIf X-Forwarded-For ^1\.2\.3\.4 allowed
(最左边的IP,转义点)
更好的方法(恕我直言)
Cloudflare 还发送 header cf-connecting-ip
(这意味着在发送到您的计算机之前最后一个访问 cloudflare 的 IP)我宁愿使用那个。
Is this a safe approach or is there a better/more secure way to limit access by client IP in Apache when Cloudflare is being used?
有个问题。在这种情况下,您要告诉 Apache:
"we have cloudflare in the middle so instead of your native way to tell the visitor's IP let's look at this custom header".
那个习俗header是可以伪造的。绝对地。因此,你也应该说:
"this custom header should be taken as reliable if and only the request comes from a Cloudflare IP".
Cloudflare does explicitly list their IP ranges
最后,您应该使用 mod_remoteip 而不是手动构建 SetEnvIf 规则。
基本上:
# /etc/apache2/conf-enabled/remoteip.conf
RemoteIPHeader CF-Connecting-IP
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
...
RemoteIPTrustedProxy 2606:4700::/32
RemoteIPTrustedProxy 2803:f800::/32
或者,将 IP 列表放在单独的文件中:
# /etc/apache2/conf-enabled/remoteip.conf
RemoteIPHeader CF-Connecting-IP
RemoteIPTrustedProxyList conf/trusted-proxies.lst
和
# conf/trusted-proxies.lst
173.245.48.0/20
103.21.244.0/22
...
...
2803:f800::/32
2606:4700::/32
如果说 header 没有出现在请求中,Apache 回退到 ro REMOTE_ADDR。来自不受信任的 IP 的请求也是如此。如果 header 存在并且来自 Cloudflare,您只需执行以下操作:
Require ip 1.2.3.4
这种方法会在您需要使用它的任何地方(日志、身份验证等)替换 IP,并在边缘情况下优雅地退回到原始 REMOTE_ADDR。