Nginx 阻止所有具有特定自定义 header 的流量,某些网址除外

Nginx block all traffic with specific custom header except to some urls

我有一个托管在内部网络中的服务,该服务在自定义负载均衡器后面的端口 443(通过 https)接收来自 Internet 和内部网络的流量。

内部网络请求带有一个额外的自定义 header,我们称之为 X-my-lb-header

我想阻止所有 uris(return 一个 http 响应代码)的所有外部传入流量,某些特定的除外。

例如,假设我想允许到达两个端点的流量 /endpoind1/(前缀匹配)和 /endpoint2 实际匹配。

实现这种行为的最佳方法是什么?

如果我的理解是正确的,我需要类似的东西(下面的语法不正确)

   location = /endpoind2 {
        if ($http_x_my_lb_header not exists) {
            pass
        } else {
            return 404
        }
        ... the rest of the directives
    }


   location ~ / {
        if ($http_x_my_lb_header) {
            return 404;
        }
        ... the rest of the directives
    }

但是由于 nginx 不支持 else,所以我想不出这样做。

有什么想法吗?

所以你需要一些像

这样的逻辑
if (header exists) {
    if (request URI isn't whitelisted) {
        block the request
    }
}

或者换句话说

if ((header exists) AND (request URI isn't whitelisted)) {
    block the request
}

嗯,nginx 不允许嵌套 if 块(也不允许逻辑条件)。虽然有些人发明了一个非常奇怪但有创意的解决方案,比如 this one (emulating AND) or even this one (emulating OR), a huge part of such a problems can be solved using map 块(一个非常强大的 nginx 功能)。

这是一个例子:

# get the $block variable using 'X-my-lb-header' value
map $http_x_my_lb_header $block {
    # if 'X-my-lb-header doesn't exists, get the value from another map block
    ''    $endpoint;
    # default value (if the 'X-my-lb-header' exists) will be an empty string
    # (unless not explicitly defined using 'default' keyword)
}

# get the $endpoint variable using request URI
map $uri $endpoint {
    # endpoint1 prefix matching (using regex)
    ~^/endpoint1    ''; don't block
    # endpoint2 exact matching
    /endpoint2      ''; don't block
    default         1; # block everything other
}

现在您可以在您的服务器块中使用此检查(不要将其放在某个位置,在 server 上下文中使用):

if ($block) { return 404; }