Todos os produtos
Search
Central de documentação

Alibaba Cloud Service Mesh:Obter o IP de origem do cliente no Alibaba Cloud Service Mesh

Última atualização: Jun 28, 2026

Este documento descreve como configurar o Service Mesh para preservar o IP de origem do cliente durante o acesso aos serviços.

Pré-requisitos

Informações de fundo

O IP de origem do cliente é utilizado em diversos cenários, incluindo:

  • Controle de acesso a aplicações: muitas aplicações exigem autenticação adicional quando um usuário faz login de uma região diferente, o que requer a obtenção do IP original do cliente.

  • Afinidade de sessão simples: realize balanceamento de carga baseado em IP de origem para encaminhar solicitações do mesmo cliente para a mesma instância de serviço.

  • Logs de acesso e monitoramento: logs e métricas contendo o endereço de origem real ajudam os desenvolvedores a analisar o tráfego e coletar estatísticas.

Balanceadores de carga na nuvem, como o Server Load Balancer (SLB), podem transmitir o IP de origem do cliente para os serviços de backend. O Istio também oferece essa capacidade. No entanto, ao usar o Istio, um proxy sidecar é injetado em cada pod. Esse proxy intercepta todo o tráfego de entrada e o encaminha para sua aplicação por meio de uma conexão local (127.0.0.1). Consequentemente, sua aplicação não consegue visualizar o IP de origem real do cliente.

Implantar aplicações de exemplo

  1. Implante a aplicação sleep.

    1. Crie um arquivo chamado sleep.yaml com o seguinte conteúdo.

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: sleep
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: sleep
        labels:
          app: sleep
          service: sleep
      spec:
        ports:
        - port: 80
          name: http
        selector:
          app: sleep
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: sleep
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: sleep
        template:
          metadata:
            labels:
              app: sleep
          spec:
            terminationGracePeriodSeconds: 0
            serviceAccountName: sleep
            containers:
            - name: sleep
              image: curlimages/curl
              command: ["/bin/sleep", "3650d"]
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - mountPath: /etc/sleep/tls
                name: secret-volume
            volumes:
            - name: secret-volume
              secret:
                secretName: sleep-secret
                optional: true
    2. Execute o comando a seguir para implantar a aplicação sleep.

      kubectl -n default apply -f  sleep.yaml
  2. Implante a aplicação httpbin.

    1. Crie um arquivo chamado httpbin.yaml com o seguinte conteúdo.

      apiVersion: v1
      kind: Service
      metadata:
        name: httpbin
        labels:
          app: httpbin
      spec:
        ports:
        - name: http
          port: 8000
        selector:
          app: httpbin
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: httpbin
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: httpbin
            version: v1
        template:
          metadata:
            labels:
              app: httpbin
              version: v1
          spec:
            containers:
            - image: docker.io/citizenstig/httpbin
              imagePullPolicy: IfNotPresent
              name: httpbin
              ports:
              - containerPort: 8000
    2. Execute o comando a seguir para implantar a aplicação httpbin.

      kubectl -n default apply -f  httpbin.yaml

Cenário 1: Tráfego leste-oeste

Etapa 1: Verificar o comportamento padrão do IP de origem do cliente

No Istio, o proxy sidecar de cada serviço intercepta todo o tráfego leste-oeste. Em seguida, esse proxy encaminha as solicitações para o contêiner da aplicação; assim, o endereço de origem visível para a aplicação é o endereço de loopback do proxy, 127.0.0.6.

  1. Execute o comando a seguir para verificar o status dos pods.

    kubectl -n default get pods -o wide

    Saída esperada:

    NAME                            READY   STATUS        RESTARTS   AGE     IP             NODE                     NOMINATED NODE   READINESS GATES
    httpbin-c85bdb469-4ll2m         2/2     Running       0          3m22s   172.17.X.XXX   cn-hongkong.10.0.0.XX    <none>           <none>
    sleep-8f764df66-q7dr2           2/2     Running       0          3m9s    172.17.X.XXX   cn-hongkong.10.0.0.XX    <none>           <none>

    A saída mostra que o endereço da aplicação sleep é 172.17.X.XXX.

  2. Execute o comando a seguir para enviar uma solicitação a partir do contêiner sleep.

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip

    Saída esperada:

    {
      "origin": "127.0.0.6"
    }

    A saída indica que o endereço de origem da solicitação recebida pela aplicação httpbin é o endereço do proxy Envoy 127.0.0.6, e não o endereço da aplicação sleep.

  3. Confirme se o endereço IP de origem é 127.0.0.6 inspecionando as informações do soquete.

    1. Faça login no contêiner httpbin e execute o comando a seguir para instalar o netstat.

      apt update & apt install net-tools
    2. Saia do contêiner httpbin e execute o comando a seguir para visualizar informações sobre a porta 8000.

      kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000

      Saída esperada:

      tcp        0      0 172.17.X.XXX:8000         127.0.0.6:42691         TIME_WAIT   -

      A saída confirma que o endereço IP de origem é 127.0.0.6.

  4. Visualize o conteúdo do log de acesso no pod httpbin.

    Veja a seguir um exemplo de entrada de log formatada:

    {
      "trace_id":null,
      "bytes_received":0,
      "upstream_host":"172.17.X.XXX:8000",
      "authority":"httpbin:8000",
      "downstream_remote_address":"172.17.X.XXX:56160",
      "upstream_service_time":"1",
      "upstream_transport_failure_reason":null,
      "istio_policy_status":null,
      "path":"/ip",
      "bytes_sent":28,
      "request_id":"4501a50a-dab0-44c9-b52c-2a4f425a****",
      "protocol":"HTTP/1.1",
      "method":"GET",
      "duration":1,
      "start_time":"2022-11-22T16:09:30.394Z",
      "user_agent":"curl/7.86.0-DEV",
      "upstream_local_address":"127.0.0.6:42169",
      "response_flags":"-",
      "route_name":"default",
      "response_code":200,
      "upstream_cluster":"inbound|80||",
      "x_forwarded_for":null,
      "downstream_local_address":"172.17.X.XXX:8000",
      "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local"
    }

    O log exibe as seguintes informações:

    • "downstream_remote_address":"172.17.X.XXX:56160": Endereço da aplicação sleep.

    • "downstream_local_address":"172.17.X.XXX:8000": Endereço de destino acessado pela aplicação sleep.

    • "upstream_local_address":"127.0.0.6:42169": Endereço local usado pelo proxy Envoy do httpbin para se conectar à aplicação httpbin. Neste ponto, o IP de origem visto pela aplicação é 127.0.0.6.

    • "upstream_host":"172.17.X.XXX:8000": Endereço de destino acessado pelo proxy Envoy do httpbin.

Etapa 2: Configurar a preservação do IP de origem

Método 1: Usar o modo TPROXY

Configure o deployment do httpbin para usar o modo de interceptação transparente TPROXY.

  1. Execute o comando a seguir para modificar o deployment da aplicação httpbin.

    kubectl patch deployment -n default httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}'                       
  2. Execute o comando a seguir para enviar uma solicitação a partir do contêiner sleep.

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip

    Saída esperada:

    {
      "origin": "172.17.X.XXX"
    }

    A saída demonstra que a aplicação httpbin obtém o endereço IP real da aplicação sleep.

  3. Execute o comando a seguir para visualizar informações sobre a porta 8000.

    Nota

    Após a reinicialização do pod, reinstale o netstat.

    kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000

    Saída esperada:

    tcp        0      0 172.17.X.XXX:8000         172.17.X.XXX:36728      ESTABLISHED -

    A saída confirma que o endereço IP de origem é 172.17.X.XXX.

  4. Visualize o conteúdo do log de acesso no pod httpbin.

    Veja a seguir um exemplo de entrada de log formatada:

    {
      "route_name":"default",
      "bytes_received":0,
      "trace_id":null,
      "request_id":"1ccabe60-63cf-469b-8565-99cac546****",
      "upstream_cluster":"inbound|80||",
      "response_flags":"-",
      "protocol":"HTTP/1.1",
      "upstream_transport_failure_reason":null,
      "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local",
      "response_code":200,
      "user_agent":"curl/7.86.0-DEV",
      "start_time":"2022-11-22T16:03:32.803Z",
      "path":"/ip",
      "authority":"httpbin:8000",
      "bytes_sent":31,
      "downstream_remote_address":"172.17.X.XXX:39058",
      "upstream_service_time":"1",
      "method":"GET",
      "downstream_local_address":"172.17.X.XXX:8000",
      "duration":1,
      "upstream_host":"172.17.X.XXX:8000",
      "istio_policy_status":null,
      "upstream_local_address":"172.17.X.XXX:46129",
      "x_forwarded_for":null
    }

    O log apresenta as seguintes informações:

    • "downstream_remote_address":"172.17.X.XXX:39058": Endereço da aplicação sleep.

    • "downstream_local_address":"172.17.X.XXX:8000": Endereço de destino acessado pela aplicação sleep.

    • "upstream_local_address":"172.17.X.XXX:46129": Endereço local usado pelo proxy Envoy do httpbin para se conectar à aplicação httpbin, correspondente ao endereço IP da aplicação sleep.

    • "upstream_host":"172.17.X.XXX:8000": Endereço de destino acessado pelo proxy Envoy do httpbin.

Método 2: Usar o cabeçalho XFF

A configuração abaixo faz com que o proxy sidecar do lado do servidor adicione um cabeçalho X-Forwarded-For (XFF) às solicitações de entrada. O proxy define o valor desse cabeçalho como o endereço IP real do cliente antes de encaminhar a solicitação para a aplicação. Este método não possui limitações de sistema operacional, mas exige que sua aplicação leia o IP de origem do cliente a partir do cabeçalho X-Forwarded-For (XFF).

  1. Aplique o EnvoyFilter a seguir na instância do ASM usando um modelo de EnvoyFilter. Para mais informações, consulte Criar um filtro Envoy usando um modelo de filtro Envoy.

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: enable-xff-for-sidecar-inbound
      namespace: istio-system  # Change this to the namespace where your gateway is located.
      labels:
        asm-system: "true"
        provider: "asm"
    spec:
      configPatches:
      - applyTo: NETWORK_FILTER
        match:
          proxy:
            proxyVersion: "^1.*"
          context: SIDECAR_INBOUND 
          listener:
            name: "virtualInbound"
            filterChain:
              filter:
                name: "envoy.filters.network.http_connection_manager"
        patch:
          operation: MERGE
          value:
            typed_config:
              "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
              use_remote_address: true
  2. Execute o comando a seguir para enviar uma solicitação a partir do contêiner sleep.

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip
  3. Saída esperada:

    {
      "origin": "172.17.X.XXX"
    }

    A saída mostra que o httpbin recebe o endereço IP real da aplicação sleep. A aplicação httpbin consegue fazer isso porque foi projetada para ler o IP de origem do cabeçalho X-Forwarded-For (XFF), agora adicionado pelo proxy sidecar. Este método não funcionará se sua aplicação não conseguir ler o cabeçalho XFF.

Cenário 2: Tráfego norte-sul

No tráfego norte-sul, as solicitações fluem de um cliente, passando por um balanceador de carga e pelo gateway de entrada do Istio, até o serviço de backend. Esse salto adicional pelo gateway de entrada torna a preservação do IP de origem do cliente mais complexa. As seções a seguir descrevem como configurar e verificar a preservação do IP de origem para solicitações HTTP e HTTPS.

Solicitações HTTP

Sem preservação do IP de origem

  1. Crie um arquivo chamado http-demo.yaml com o seguinte conteúdo para acessar a aplicação httpbin via HTTP.

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gw-httpprotocol
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: http
            number: 80
            protocol: HTTP
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
        - httpbin-gw-httpprotocol
      hosts:
        - '*'
      http:
        - route:
            - destination:
                host: httpbin
                port:
                  number: 8000
  2. Execute o comando a seguir para implantar o gateway e o VirtualService.

    kubectl -n default apply -f  http-demo.yaml
  3. Execute o comando a seguir para acessar a aplicação httpbin através do gateway de entrada.

    export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    curl http://$GATEWAY_URL:80/ip

    Saída esperada:

    {
      "origin": "10.0.0.93"
    }

    A saída indica que o endereço IP retornado corresponde a um nó do Kubernetes.

  4. Visualize o log de acesso do gateway de entrada.

    Veja a seguir um exemplo de entrada de log:

    {
      "upstream_service_time":"1",
      "response_code":200,
      "protocol":"HTTP/1.1",
      "bytes_sent":28,
      "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local",
      "start_time":"2022-11-23T03:29:20.017Z",
      "istio_policy_status":null,
      "upstream_transport_failure_reason":null,
      "trace_id":null,
      "route_name":null,
      "request_id":"292903be-a889-4d5d-83a0-ab1f5d1a****",
      "method":"GET",
      "upstream_host":"172.17.X.XXX:8000",
      "duration":1,
      "path":"/ip",
      "downstream_local_address":"172.17.X.XXX:80",
      "authority":"47.242.XXX.XX",
      "user_agent":"curl/7.79.1",
      "downstream_remote_address":"10.0.0.93:5899",
      "upstream_local_address":"172.17.X.XXX:54322",
      "requested_server_name":null,
      "x_forwarded_for":"10.0.0.93",
      "response_flags":"-",
      "bytes_received":0
    }

    O log exibe as seguintes informações:

    • "downstream_remote_address":"10.0.0.93:5899": Não é o IP de origem real do cliente.

    • "downstream_local_address":"172.17.X.XXX:80": Endereço do pod do gateway de entrada.

    • "upstream_local_address":"172.17.X.XXX:54322": Endereço IP do pod do gateway de entrada preservado, mas com número de porta alterado.

    • "upstream_host":"172.17.X.XXX:8000": Endereço do pod httpbin.

With source IP preservation

  1. Defina a política de tráfego externo como Local. (Ignore esta etapa para clusters que usam o modo de rede Terway.)

    1. Faça login no console do ASM. No painel de navegação à esquerda, escolha Service Mesh > Mesh Management.

    2. Na página Mesh Management, clique em no nome da instância do ASM. No painel de navegação à esquerda, escolha ASM Gateways > Ingress Gateway.

    3. Na página Ingress Gateway, clique em View YAML à direita do gateway desejado.

    4. Na caixa de diálogo Edit, localize a seção spec, defina o campo externalTrafficPolicy como Local e clique em OK.

      spec:
        affinity: {}
        autoCreateGatewayYaml: false
        clusterIds:
          - cf0243f2c3009406xxx
        compression: {}
        cpu: {}
        dnsPolicy: ClusterFirst
        externalTrafficPolicy: Local
        gatewayType: ingress
  2. Execute o comando a seguir para acessar a aplicação httpbin através do gateway de entrada.

    curl http://$GATEWAY_URL:80/ip

    Saída esperada:

    {
      "origin": "120.244.xxx.xxx"
    }

    A saída confirma que o endereço IP retornado é o IP de origem real do cliente.

  3. Visualize o log de acesso do gateway de entrada.

    Veja a seguir um exemplo de entrada de log:

    {
      "istio_policy_status":null,
      "upstream_transport_failure_reason":null,
      "path":"/ip",
      "x_forwarded_for":"120.244.XXX.XXX",
      "route_name":null,
      "method":"GET",
      "duration":2,
      "downstream_remote_address":"120.244.XXX.XXX:28504",
      "bytes_received":0,
      "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local",
      "bytes_sent":34,
      "protocol":"HTTP/1.1",
      "response_flags":"-",
      "upstream_local_address":"172.17.X.XXX:57498",
      "upstream_service_time":"2",
      "request_id":"9c0295d4-e77f-4a3a-b292-e5c58d92****",
      "start_time":"2022-11-23T03:24:04.413Z",
      "response_code":200,
      "trace_id":null,
      "authority":"47.242.XXX.XX",
      "user_agent":"curl/7.79.1",
      "downstream_local_address":"172.17.X.XXX:80",
      "upstream_host":"172.17.X.XXX:80",
      "requested_server_name":null
    }

    O log apresenta as seguintes informações:

    • "downstream_remote_address":"120.244.XXX.XXX:28504": Endereço de origem do cliente, conforme esperado.

    • "downstream_local_address":"172.17.X.XXX:80": Endereço do pod do gateway de entrada.

    • "upstream_local_address":"172.17.X.XXX:57498": Endereço do pod do gateway de entrada preservado, mas com número de porta alterado.

    • "upstream_host":"172.17.X.XXX:80": Endereço do pod httpbin.

Solicitações HTTPS

Como a seção anterior detalhou as solicitações HTTP, esta seção foca apenas na configuração e verificação para solicitações HTTPS.

  1. Configure a preservação do IP de origem.

  2. Crie um arquivo chamado https-demo.yaml com o seguinte conteúdo para acessar a aplicação httpbin via HTTPS.

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gw-https
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: https
            number: 443
            protocol: HTTPS
          tls:
            credentialName: myexample-credential
            mode: SIMPLE
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin-https
      namespace: default
    spec:
      gateways:
        - httpbin-gw-https
      hosts:
        - '*'
      http:
        - route:
            - destination:
                host: httpbin
                port:
                  number: 8000
  3. Execute o comando a seguir para implantar o gateway e o VirtualService.

    kubectl -n default apply -f  https-demo.yaml
  4. Execute o comando a seguir para acessar a aplicação httpbin através do gateway de entrada.

    export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    curl -k https://$GATEWAY_URL:443/ip

    Saída esperada:

    {
      "origin": "120.244.XXX.XXX"
    }

    A saída confirma que o endereço IP retornado é o IP de origem real do cliente.