对来源 IP 进行限制

使用 allow 和 deny 指令进行控制

  1. server {
  2. # 192.168.0.0/16 网段只允许 192.168.0.1 访问
  3. deny 192.168.0.1;
  4. allow 192.168.0.0/16;
  5. allow 10.0.0.1;
  6. allow 10.0.0.2;
  7. allow 10.1.0.0/16;
  8. # 除了以上 allow 的 IP 外,其他来源 IP 都无法访问
  9. deny all;
  10. }

使用 geo 指令进行控制

  1. http {
  2. geo $remote_addr $deny_ip {
  3. # 默认值所有 IP 都无法访问
  4. default 1;
  5. 192.168.0.1 1;
  6. 192.168.0.0/16 0;
  7. 10.1.0.1 1;
  8. 10.1.0.2 1;
  9. 10.1.0.0/16 0;
  10. }
  11. server {
  12. # 如果 deny_ip 的值为 1,则表示禁止访问
  13. if ($deny_ip) {
  14. return 403;
  15. }
  16. }
  17. }

geo 指令还支持 ranges,对 ip 段进行限制

  1. geo $remote_addr $deny_ip_range {
  2. ranges;
  3. default 1;
  4. 192.168.0.5-192.168.0.7 0;
  5. 127.0.0.1-127.0.0.255 0;
  6. }

对要访问的域名进行限制

使用 if 语句进行控制

  1. server {
  2. # 如果不是形如:foo.com、www.foo.com、www.sub.foo.com 域名则禁止访问
  3. if ($http_host !~ '^(.*\.)?(foo\.com|bar\.com)$') {
  4. return 403;
  5. }
  6. }

使用 map 指令进行控制

  1. http {
  2. map $http_host $deny_host {
  3. hostnames;
  4. default 1;
  5. # 能匹配 foo.com、www.foo.com、www.sub.foo.com
  6. .foo.com 0;
  7. .bar.com 0;
  8. }
  9. server {
  10. # 如果不在允许访问的域名白名单中,则禁止访问
  11. if ($deny_host) {
  12. return 403;
  13. }
  14. }
  15. }

IF AND 条件书写方式

在大多情况下,使用 map 或者 geo 比使用 if 做判断更为简洁。if 在判断多个条件同时成立的情况依然有用。

  1. if ($scheme = 'http') {
  2. set $test A;
  3. }
  4. if ($request_uri = /) {
  5. set $test "${test}B";
  6. }
  7. if ($http_host = 'foo.com') {
  8. set $test "${test}C";
  9. }
  10. # 当不满足 3 个条件时,则禁止访问
  11. if ($test != ABC) {
  12. return 403;
  13. }

参考文献