我有以下 NGINX 配置文件:
worker_processes 4;
worker_rlimit_nofile 40000;
events {
worker_connections 8192;
}
stream {
upstream rancher_servers_http {
least_conn;
server <IP_NODE_1>:80 max_fails=3 fail_timeout=5s;
server <IP_NODE_2>:80 max_fails=3 fail_timeout=5s;
server <IP_NODE_3>:80 max_fails=3 fail_timeout=5s;
}
server {
listen 80;
proxy_pass rancher_servers_http;
}
upstream rancher_servers_https {
least_conn;
<IP_NODE_1>:443 max_fails=3 fail_timeout=5s;
<IP_NODE_2>:443 max_fails=3 fail_timeout=5s;
<IP_NODE_3>:443 max_fails=3 fail_timeout=5s;
}
server {
listen 443;
proxy_pass rancher_servers_https;
}
}
我想将子域的某些 IP 列入白名单*.dev.mydomain.com
。
我尝试将其添加到服务器块:
if ($host ~ *.dev.mydomain.com) {
allow: <ip1>,<ip2>
deny: all;
}
但是我遇到了以下错误:
nginx:[emerg]此处不允许使用“if”指令
然后我尝试添加一个map
。在服务器块下我还有一个,directive not allowed here
但我可以在流块内添加地图。
当我在流块上添加地图时,如下所示:
map $hostname $deny_ips {
default all;
~*.dev.mydomain.com all;
}
我无法deny_ips
在服务器块中使用该变量,我得到了一个
[emerg] /etc/nginx/nginx.conf:35 中的参数“deny_ips”无效
还要注意的是,我无法映射$host
,但我只能映射$hostname
,或者我得到了一个
nginx:[emerg] 未知的“主机”变量
有人可以帮我根据子域名将某些 IP 列入白名单吗?
谢谢。
答案1
我尝试用找到解决方案,nginx
但没有取得很大进展;我用了一个http阻止常规 HTTP 流量(此部分工作正常)以及溪流SSL 块(有关详细信息,请参阅答案的第二部分)。
不过我认为哈普罗西可以在这里使用,因为在配置 ACL 时它似乎更加灵活。
haproxy 解决方案
global
maxconn 20000
log 127.0.0.1 local0
user haproxy
chroot /usr/share/haproxy
pidfile /run/haproxy.pid
daemon
defaults
timeout connect 10s
timeout client 30s
timeout server 30s
frontend ssl
bind *:443
mode tcp
acl network_allowed src 192.168.1.0/24 192.168.2.3/32 <-- EDIT IPs
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl dev_domain req_ssl_sni -m end .dev.mydomain.com <-- EDIT domain
tcp-request content reject if !network_allowed dev_domain
use_backend rancher_servers_https
backend rancher_servers_https
balance leastconn
mode tcp
server node1 1.2.3.4:443 fall 3 rise 2 <-- EDIT IP
server node2 2.3.4.5:443 fall 3 rise 2 <-- EDIT IP
server node3 3.4.5.6:443 fall 3 rise 2 <-- EDIT IP
我标记了您需要编辑配置的位置,您可能global
还需要调整该部分(取决于您的发行版)。
以上是 SSL 部分;非加密部分应该类似,但没有 SNI/SSL 部分。请注意,我还没有尝试过这个,我以前也没有用过 haproxy,但我认为它会让您走上正确的道路。
nginx 解决方案 - 不完整
我使用地图$ssl_preread_server_name
通过获取域名信噪比以及geo
用于匹配不允许的 IP 的块。
map $ssl_preread_server_name $dev_upstream {
hostnames;
*.dev.mydomain.com 1;
default 0;
}
geo $not_dev_whitelist {
default 1;
192.168.1.0/24 0;
2001:0db8::/32 0;
}
但是因为if
流块中不允许所以我不能这样做:
server {
listen 443;
if ($dev_upstream) {
set $dev "1";
}
if ($not_dev_whitelist) {
set $dev "${dev}1";
}
if ($dev = "11") {
return "blocked";
}
proxy_pass rancher_servers_https;
}
答案2
首先,Nginx 不允许嵌套 if 语句。您需要使用 map 功能来实现您的目标。
第二,你对地图工具的使用是错误的
map "$http_referer:$arg_78up" $refernotok {
default 1;
~ mywebsite.com.*:.*$ 0;
~ ^.+:.+$ 0;
}
if ($refernotok = "1") {
return 404;
}
您应该在地图中使用 $http_referer。
第一部分是正则表达式。^ 表示字符串的开始,.+ 表示一个或多个字符,: 是分隔符,然后我们再次用 .+ 匹配一个或多个字符,最后我们需要以 $ 结尾的字符串。0 是正则表达式匹配时 $refernotok 变量获取的值。
答案3
只需使用两个服务器块。
server {
listen 80 default_server;
server_name _;
proxy_pass rancher_servers_http;
}
server {
listen 80;
server_name *.dev.mydomain.com;
allow <ip1>;
allow <ip2>;
deny all;
proxy_pass rancher_servers_http;
}
.. same for the server on :443
另外,如果您使用 nginx-ingress,则可以使用注释将 IP 列入白名单。请参阅文档。我发现它比手动配置 nginx 更容易管理。