簡體   English   中英

如何在docker中通過usig nginx獲取真實客戶端ip

[英]How to get the real client ip by usig nginx in docker

我使用 .NET Core 后端、角度前端和 nginx 作為 docker 網絡中的反向代理。 我從本地瀏覽器或同一局域網中的另一個客戶端調用前端。 因此沒有使用額外的代理。 我現在嘗試確定客戶端的真實 IP 地址。 我得到了幾個未知的 IP 地址,我無法 ping,但不是客戶端之一。

我做錯了什么或者我忘記了什么?

這里是 Startup.cs 的一部分:

virtual public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders =
            ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });

    ...
}

virtual public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
        ForwardLimit = null, // null = disable check
        RequireHeaderSymmetry = false,
        //KnownProxies = { IPAddress.Parse("<IP Adresse 1>")},
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseAuthentication();

    app.UseMvc();           
}

這里是 nginx.conf:

worker_processes  1;
error_log  /etc/nginx/logs/error.log;

events { 
}

http {

  map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }

  upstream ${SERVER_NAME} {
    server backend_app:4200;
    server 127.0.0.1:4200;
  }

  server {
    listen 443 ssl; 

    server_name ${SERVER_NAME};
    keepalive_timeout   70;

    ssl_certificate /etc/nginx/certs/cert.crt;
    ssl_certificate_key /etc/nginx/certs/cert.key;

    ssl_prefer_server_ciphers on;
    ssl_session_timeout 10m;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    location / {
        proxy_pass http://${SERVER_NAME};
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
  }
}

減少docker-compose:

version: '3.7'

services:
  frontproxy:
    networks:
      frontproxy_default: {}
      public_net:
        ipv4_address: 192.168.165.137
  application_app:    
    networks:
      frontproxy_default: {}
      test_network: {}   
  application_sql:    
    networks:
      - test_network   
  application_api:    
    container_name: api
    networks:
      - test_network

networks:
  test_network:
    name: test_network
  frontproxy_default:
    name: frontproxy_default
  public_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.0.0/24
          #gateway: 192.168.165.1

如果您想控制 docker 鏡像的 IP 地址,更好的辦法是自己設置整個編排。

Docker-compose yaml 文件為您提供了自己設置 IP 地址的選項。

docker-compose 默認提供網絡並自行分配 IP 地址。 您可以使用自定義網絡覆蓋默認網絡。

docker-compose.yaml文件應如下所示:

就我而言,DB 是 mysql 服務器,API 是 .NET Core WebAPI 項目。 WEB1/2 是兩個前端服務器,對我來說又是 .NET Core MVC 項目。

version: '3.3'
services:
  moviedb:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: password@123
      MYSQL_DATABASE: moviedb
      MYSQL_USER: movieadmin
      MYSQL_PASSWORD: password@123
    volumes:
      - C:\MvcMovie:/var/lib/mysql
      - ./MvcMovie/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      public_net:
        ipv4_address: ${MVCMOVIE_DB_1_IP}
  movieapi:
    build: 
        context: .
        dockerfile: Dockerfile.api
    depends_on:
      - moviedb
    networks:
      public_net:
        ipv4_address: ${MVCMOVIE_API_1_IP}
  movieweb1:
    build: 
        context: .
        dockerfile: Dockerfile.web
    networks:
      public_net:
        ipv4_address: ${MVCMOVIE_WEB_1_IP}
  movieweb2:
    build: 
        context: .
        dockerfile: Dockerfile.web
    networks:
      public_net:
        ipv4_address: ${MVCMOVIE_WEB_2_IP}
  haproxy:
    image: haproxy
    ports:
      - 8080:80
    expose:
      - 80
    networks:
      public_net:
         ipv4_address: ${HA_PROXY_IP}
    environment:
      - MVCMOVIE_API_1_IP=${MVCMOVIE_API_1_IP}
      - MVCMOVIE_WEB_1_IP=${MVCMOVIE_WEB_1_IP}
      - MVCMOVIE_WEB_2_IP=${MVCMOVIE_WEB_2_IP}
      - MVCMOVIE_EXPOSED_PORT=${MVCMOVIE_EXPOSED_PORT}
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
networks:
  public_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: ${NETWORK_SUBNET}

特別注意縮進。

在 docker-compose.yaml 旁邊添加一個 .env 文件並使用類似的內容,如下所示。 更改名稱和端口以滿足需要。

MVCMOVIE_EXPOSED_PORT=80

MVCMOVIE_DB_1_IP=192.168.0.10

MVCMOVIE_API_1_IP=192.168.0.20

MVCMOVIE_WEB_1_IP=192.168.0.30
MVCMOVIE_WEB_2_IP=192.168.0.31


HA_PROXY_IP=192.168.0.100

NETWORK_SUBNET=192.168.0.0/24

照這樣說。 您永遠不應該針對 IP 地址進行編碼。 如果我是你,我會執行以下操作之一:

  1. 請改用服務名稱。
  2. 將 IP 地址的設置放在 .env 文件中,並在 ipv4_address: ${server1_ip_address} 或類似的地方使用環境變量。
  3. 考慮使用 Kubernetes。 讓您的后端服務器位於負載平衡器后面。

祝你好運。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM