在我的服务器(具有单个 IP 地址)上,多个服务在不同的端口上运行。Nginx 也在端口 80 和 443 上运行,以根据域请求提供页面。所有服务和 nginx 都是通过 docker-compose 启动的。如何使用 nginx、iptables、防火墙和其他开发工具拒绝对 IP 地址的所有外部请求(例如,对 56.56.56.56:3000 或对 56.56.56.56)但同时允许对域名的所有请求?一切都在 Ubutntu 服务器 22.04 上运行
nginx.conf
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
server {
listen 80 default_server;
server_name my.domain www.my.domain;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name my.domain;
ssl_certificate /etc/nginx/ssl/my.domain/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/my.domain/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 10s;
send_timeout 10s;
location / {
proxy_pass http://56.56.56.56:3002; # адрес для примера
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
limit_conn conn_limit_per_ip 10;
limit_req zone=req_limit_per_ip burst=10 nodelay;
}
}
...
}
docker-compose.yml
...
site:
build:
context: ...
dockerfile: Dockerfile
restart: unless-stopped
ports:
- "3002:3002"
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
nginx:
image: nginx:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/ssl/:/etc/nginx/ssl/
grafana:
image: grafana/grafana:latest
ports:
- '3000:3000'
volumes:
- grafana-data:/var/lib/grafana
...
提前致谢!
重要信息
-
如果我尝试通过 iptables 限制外部 TCP 请求并仅允许内部请求(以便请求只能通过 nginx 从外部发送,即发送到域名),防火墙甚至会阻止通过 nginx 的请求。我认为在向域发送请求时,它们会通过 nginx 路由,因此防火墙认为该请求是从本地 IP 发送的。
-
如果我在机器本地运行所有服务(例如
app.run("127.0.0.1", port=3000)
),nginx 不会检测到这一点,这意味着proxy_pass http://127.0.0.1:3000
将无法工作。我原本打算在本地运行所有服务,这样它们就无法直接从外部访问,但 nginx 仍然可以访问它们,因为它在同一个容器中运行,但只能通过域请求。然而,由于某种原因,当 nginx 尝试请求时,我收到“连接被拒绝”错误127.0.0.1
。
1
最佳答案
1
您的容器网络暴露了不必要的主机端口。
- 删除除外部代理
ports
之外docker-compose.yml
的所有内容的外部代理,在本例中名为nginx
。 - 将这些前端和后端容器保持在同一个 docker-compose 网络中。
- 使用容器名称在网络上相互引用。proxy_pass 到后端
http://site:3002
和http://grafana:3000
导致您的容器定义也生成了具有区域概念的防火墙。容器可以相互访问,但外部主机流量只能通过端口进入 nginx。无需额外手动生成的私有网络和防火墙规则即可实现此隔离。
此 IP 级网络和防火墙不关心您的 http 名称虚拟主机。但是,该 nginx 配置已在应用程序级别需要名称。并且 https 重定向将让用户代理也验证名称。(具有 IP 地址主体的证书在理论上是可行的,但与 (DNS) 名称相比,几乎没有人使用它们。)
不指定 IP 地址可使您的地址计划更加灵活。
- 如果反向代理不是通过环回地址,则容器可以在不同的主机上运行。
- 当您实现 IPv6 地址时,您不再需要担心地址空间重叠。您应该使用的所有空间都是互联网可路由的,但这没关系。容器地址之间的区别
2001:db8:116:7483::a
可能::b
在于一个暴露主机端口,而另一个不暴露。
|
http://grafana:3000
。–
|