Nginx阻止所有具有特定自定义头的流量,除了一些URL

btqmn9zl  于 2023-05-16  发布在  Nginx
关注(0)|答案(1)|浏览(176)

我有一个托管在内部网络中的服务,它在自定义负载均衡器后面的端口443(通过https)接收流量,这些流量来自互联网和内部网络。
内部网络请求带有一个额外的自定义头,我们称之为X-my-lb-header
我想阻止所有外部传入的流量到所有的uri(返回一个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,所以我不知道怎么做。
有什么想法吗

ffscu2ro

ffscu2ro1#

所以你需要一些逻辑比如

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(模拟AND)甚至this one(模拟OR),但很大一部分问题可以使用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; }

相关问题