haproxy 解决方案

haproxy 解决方案

我有以下 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 更容易管理。

相关内容