Usando as políticas de rede do Calico para controlar o tráfego em clusters clássicos

Saiba como usar as políticas do Calico para permitir o tráfego de rede de e para determinados endereços IP.

Observe que as etapas a seguir são para clusters clássicos com LoadBalancers clássicos.

Por padrão, os serviços NodePort, LoadBalancer e Ingresso do Kubernetes disponibilizam o seu app em todas as interfaces de rede de cluster pública e privada. A política padrão allow-node-port-dnat do Calico permite o tráfego recebido de serviços NodePort, de balanceador de carga de rede (NLB) e de balanceador de carga do app (ALB) Ingress para os pods de app que esses serviços expõem. O Kubernetes usa a conversão de endereço de rede de destino (DNAT) para encaminhar as solicitações de serviço para os pods corretos.

No entanto, por razões de segurança, pode ser necessário permitir o tráfego para os serviços de rede somente de determinados endereços IP de origem. É possível usar políticas pré-DNAT do Calico para permitir ou bloquear o tráfego de ou para determinados endereços IP. As políticas pré-DNAT evitam que o tráfego especificado atinja seus apps porque elas são aplicadas antes que o Kubernetes use DNAT regular para encaminhar tráfego para os pods. Ao criar políticas pré-DNAT do Calico, você escolhe se deseja permitir ou bloquear os endereços IP de origem. Para a maioria dos cenários, a permissão de um tráfego específico fornece a configuração mais segura, pois todo o tráfego é bloqueado, exceto aquele de endereços IP de origem permitidos. A negação de um tráfego específico normalmente é útil apenas em cenários como, por exemplo, para prevenir um ataque por meio de um pequeno conjunto de endereços IP.

Neste cenário, você desempenha a função de um administrador de rede para uma firma de RP e observa algum tráfego incomum que atinge seus apps. As lições deste tutorial fornecem orientação durante a criação de um app de servidor da web de amostra, expondo o app ao usar um serviço balanceador de carga de rede (NLB) e protegendo-o contra tráfego incomum indesejado com as políticas Calico de lista de permissões e de lista de bloqueios.

Objetivos

  • Aprenda a bloquear todo o tráfego recebido para todas as portas de nó, criando uma política pré-DNAT de alta ordem.
  • Saiba como permitir que endereços IP de origem específicos acessem o IP público e a porta do NLB, criando uma política pré-DNAT de baixa ordem. As políticas de ordem inferior substituem as políticas de ordem superior.
  • Saiba como impedir que endereços IP de origem específicos acessem o IP público e a porta do NLB, criando uma política pré-DNAT de baixa ordem.

Público

Este tutorial é destinado a desenvolvedores de software e administradores de rede que desejam gerenciar o tráfego de rede para um app.

Pré-requisitos

Implementar um app e expô-lo usando um NLB

A primeira lição mostra como seu app é exposto por meio de múltiplos endereços IP e portas e onde o tráfego público está chegando em seu cluster.

Inicie implementando um app de servidor da web de amostra para usar em todo o tutorial. O servidor da web echoserver mostra dados sobre a conexão que é feita com o cluster por meio do cliente e é possível testar o acesso ao cluster da firma PR. Em seguida, exponha o app ao criar um serviço do balanceador de carga de rede (NLB) 1.0. Um serviço NLB 1.0 torna seu app disponível por meio do endereço IP do serviço NLB e das portas de nó dos nós do trabalhador.

No final da lição 1, o aplicativo do servidor Web está exposto à Internet pela porta do nó público e pelo NLB público.

  1. Implemente o app do servidor da web de amostra. Quando uma conexão é feita com o app do servidor da web, o app responde com os cabeçalhos de HTTP que ele recebeu na conexão.

    kubectl apply -f https://raw.githubusercontent.com/IBM-Cloud/kube-samples/master/deploy-apps-clusters/webserver.yaml
    
  2. Verifique se os pods de app de servidor da web têm um STATUS de Running.

    kubectl get pods -o wide
    

    Saída de exemplo

    NAME                         READY     STATUS    RESTARTS   AGE       IP               NODE
    webserver-855556f688-6dbsn   1/1       Running   0          1m        172.30.xxx.xxx   10.176.48.78
    webserver-855556f688-76rkp   1/1       Running   0          1m        172.30.xxx.xxx   10.176.48.78
    webserver-855556f688-xd849   1/1       Running   0          1m        172.30.xxx.xxx   10.176.48.78
    
  3. Para expor o app à Internet pública, crie um arquivo de configuração do serviço NLB 1.0 chamado webserver-lb.yaml em um editor de texto.

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        run: webserver                               
      name: webserver-lb
    spec:
      type: LoadBalancer
      selector:
        run: webserver
      ports:
      - name: webserver-port
        protocol: TCP
        port: 8080
        targetPort: 8080 # Optional. By default, the `targetPort` is set to match the `port` value unless specified otherwise.
    
  4. Implemente o NLB.

    kubectl apply -f filepath/webserver-lb.yaml
    
  5. Verifique se é possível acessar publicamente o app que é exposto pelo NLB de seu computador.

    1. Obtenha o endereço EXTERNAL-IP público do NLB.

      kubectl get svc -o wide
      

      Saída de exemplo

      NAME           CLUSTER-IP       EXTERNAL-IP        PORT(S)        AGE       SELECTOR
      webserver-lb   172.21.xxx.xxx   169.xx.xxx.xxx     80:31024/TCP   2m        run=webserver
      
    2. Crie um arquivo de texto de folha de dicas e copie o IP do NLB para ele. A folha de dicas ajuda a usar mais rapidamente os valores em lições posteriores.

    3. Verifique se é possível acessar publicamente o IP externo para o NLB.

      curl --connect-timeout 10 <loadbalancer_IP>:80
      

      A saída de exemplo a seguir confirma que o NLB expõe seu app no endereço IP 169.1.1.1 do NLB público. O pod do app webserver-855556f688-76rkp recebeu a solicitação de curl.

      Hostname: webserver-855556f688-76rkp
      Pod Information:
          -no pod information available-
      Server values:
          server_version=nginx: 1.13.3 - lua: 10008
      Request Information:
          client_address=10.176.XX.XX
          method=GET
          real path=/
          query=
          request_version=1.1
          request_scheme=http
          request_uri=http://169.1.1.1:8080/
      Request Headers:
          accept=*/*
          host=169.1.1.1
          user-agent=curl/7.54.0
      Request Body:
          -no body in request-
      
  6. Verifique se é possível acessar publicamente o app que é exposto pela porta de nó de seu computador. Um serviço NLB torna seu app disponível por meio do endereço IP do serviço NLB e das portas de nó dos nós do trabalhador.

    1. Obtenha a porta de nó que o NLB designou aos nós do trabalhador. A porta de nó está no intervalo 30000 - 32767.

      kubectl get svc -o wide
      

      Na saída de exemplo a seguir, a porta de nó é 31024:

      NAME           CLUSTER-IP       EXTERNAL-IP        PORT(S)        AGE       SELECTOR
      webserver-lb   172.21.xxx.xxx   169.xx.xxx.xxx     80:31024/TCP   2m        run=webserver
      
    2. Para clusters clássicos, obtenha o endereço IP público de um nó do trabalhador. Para clusters VPC, obtenha o endereço IP privado como alternativa.

      ibmcloud ks worker ls --cluster <cluster_name>
      

      Saída de exemplo

      ID                                                 Public IP        Private IP     Machine Type        State    Status   Zone    Version   
      kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w1   169.xx.xxx.xxx   10.176.48.67   u3c.2x4.encrypted   normal   Ready    dal10   1.35_1513*   
      kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w2   169.xx.xxx.xxx   10.176.48.79   u3c.2x4.encrypted   normal   Ready    dal10   1.35_1513*   
      kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w3   169.xx.xxx.xxx   10.176.48.78   u3c.2x4.encrypted   normal   Ready    dal10   1.35_1513*   
      
    3. Copie o IP público do nó do trabalhador e a porta de nó em sua folha de dicas de texto para usar em lições mais recentes.

    4. Verifique se é possível acessar o endereço IP público do nó do trabalhador por meio da porta de nó. Nota: como os nós do trabalhador em clusters de VPC não têm um endereço IP público, só será possível acessar um app através de um NodePort se você estiver conectado à rede privada VPC, como por meio de uma conexão VPN. Em seguida, é possível utilizar o endereço IP privado do nó do trabalhador e NodePort: <worker_private_IP>:<NodePort>.

      curl  --connect-timeout 10 <worker_IP>:<NodePort>
      

      A saída de exemplo a seguir confirma que a solicitação para seu app veio por meio do endereço IP privado 10.1.1.1 para o nó do trabalhador e a porta de nó 31024. O pod de app webserver-855556f688-xd849 recebeu a solicitação de curl:

      Hostname: webserver-855556f688-xd849
      Pod Information:
          -no pod information available-
      Server values:
          server_version=nginx: 1.13.3 - lua: 10008
      Request Information:
          client_address=1.1.1.1
          method=GET
          real path=/
          query=
          request_version=1.1
          request_scheme=http
          request_uri=http://10.1.1.1:8080/
      Request Headers:
          accept=*/*
          host=10.1.1.1:31024
          user-agent=curl/7.60.0
      Request Body:
          -no body in request-
      

Neste momento, seu app é exposto por meio de múltiplos endereços IP e portas. A maioria desses IPs é interna para o cluster e pode ser acessada somente por meio da rede privada. Somente a porta de nó pública e a porta do NLB público são expostas à Internet pública.

Em seguida, é possível iniciar a criação e aplicação de políticas do Calico para bloquear o tráfego público.

Bloquear todo o tráfego de entrada para todas as portas do nó

Para proteger o cluster da firma PR, deve-se bloquear o acesso público ao serviço NLB e às portas de nó que estão expondo o app. Inicie bloqueando o acesso às portas de nó.

No final da Lição 2, o aplicativo do servidor Web é exposto à Internet somente por NLB público.

  1. Em um editor de texto, crie uma política pré-DNAT de alta ordem chamada deny-nodeports.yaml para negar o tráfego TCP e UDP recebido de qualquer IP de origem para todas as portas de nó.

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: deny-nodeports
    spec:
      applyOnForward: true
      preDNAT: true
      ingress:
      - action: Deny
        destination:
          ports:
          - 30000:32767
        protocol: TCP
        source: {}
      - action: Deny
        destination:
          ports:
          - 30000:32767
        protocol: UDP
        source: {}
      selector: ibm.role=='worker_public'
      order: 1100
      types:
      - Ingress
    
  2. Aplique a política.

    • Linux:

      calicoctl apply -f filepath/deny-nodeports.yaml
      
    • Windows e OS X:

      calicoctl apply -f filepath/deny-nodeports.yaml --config=filepath/calicoctl.cfg
      

    Saída de exemplo

    Successfully applied 1 'GlobalNetworkPolicy' resource(s)
    
  3. Usando os valores de sua folha de dicas, verifique se não é possível acessar publicamente o endereço IP e a porta de nó públicos do nó do trabalhador.

    curl  --connect-timeout 10 <worker_IP>:<NodePort>
    

    A conexão atinge o tempo limite porque a política do Calico que você criou está bloqueando o tráfego para as portas de nó.

    curl: (28) Connection timed out after 10016 milliseconds
    
  4. Mude a externalTrafficPolicy do LoadBalancer criada na lição anterior de Cluster para Local. O Local assegura que o IP de origem do sistema será preservado quando um curl for emitido para o IP externo do LoadBalancer na próxima etapa.

    kubectl patch svc webserver-lb -p '{"spec":{"externalTrafficPolicy":"Local"}}'
    
  5. Usando o valor de sua folha de dicas, verifique se ainda é possível acessar publicamente o endereço IP externo do NLB.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    

    Saída de exemplo

    Hostname: webserver-855556f688-76rkp
    Pod Information:
        -no pod information available-
    Server values:
        server_version=nginx: 1.13.3 - lua: 10008
    Request Information:
        client_address=1.1.1.1
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://<loadbalancer_IP>:8080/
    Request Headers:
        accept=*/*
        host=<loadbalancer_IP>
        user-agent=curl/7.54.0
    Request Body:
        -no body in request-
    

    Na seção Request Information da saída, o endereço IP de origem é, por exemplo, client_address=1.1.1.1. O endereço IP de origem é o IP público do sistema que você está usando para executar curl. Caso contrário, se você estiver se conectando à Internet por meio de um proxy ou uma VPN, o proxy ou a VPN poderá estar obscurecendo o endereço IP real do seu sistema. Em qualquer um dos casos, o NLB considera o endereço IP de origem do seu sistema como o endereço IP do cliente.

  6. Copie o endereço IP de origem do seu sistema (client_address=1.1.1.1 na saída de etapa anterior) em sua folha de dicas para usar em lições posteriores.

Ótimo! Neste ponto, seu app é exposto à Internet pública somente por meio da porta do NLB público. O tráfego para as portas de nó público está bloqueado. Seu cluster está parcialmente bloqueado do tráfego indesejado.

Em seguida, é possível criar e aplicar políticas do Calico para permitir o tráfego apenas de determinados IPs de origem.

Permitir o tráfego de entrada de um IP específico para o NLB

Agora você decide bloquear completamente o tráfego para o cluster da firma PR e testar o acesso, permitindo apenas o endereço IP do seu próprio computador.

Primeiro, além das portas de nó, deve-se bloquear todo o tráfego recebido para o NLB que está expondo o app. Em seguida, é possível criar uma política que permita o endereço IP do seu sistema. No final da Lição 3, todo tráfego para as portas do nó público e o NLB é bloqueado e apenas o tráfego de seu IP do sistema permitido é aceito.

  1. Em um editor de texto, crie uma política Pré-DNAT de alta ordem chamada deny-lb-port-80.yaml para negar todo o tráfego TCP e UDP recebido de qualquer IP de origem para o endereço IP e a porta do NLB. Substitua <loadbalancer_IP> pelo endereço IP público do NLB da folha de dicas.

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: deny-lb-port-80
    spec:
      applyOnForward: true
      preDNAT: true
      ingress:
      - action: Deny
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: TCP
        source: {}
      - action: Deny
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: UDP
        source: {}
      selector: ibm.role=='worker_public'
      order: 800
      types:
      - Ingress
    
  2. Aplique a política.

    • Linux:

      calicoctl apply -f filepath/deny-lb-port-80.yaml
      
    • Windows e OS X:

      calicoctl apply -f filepath/deny-lb-port-80.yaml --config=filepath/calicoctl.cfg
      
  3. Usando o valor de sua folha de dicas, verifique se agora não é possível acessar o endereço IP público do NLB. A conexão atinge o tempo limite porque a política do Calico criada está bloqueando o tráfego para o NLB.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    
  4. Em um editor de texto, crie uma política pré-DNAT de baixa ordem chamada allowlist.yaml para permitir o tráfego do IP do seu sistema para o endereço IP e a porta do NLB. Usando os valores da folha de dicas, substitua <loadbalancer_IP> pelo endereço IP público do NLB e <client_address> pelo endereço IP público do IP de origem do sistema. Se não for possível se lembrar de seu IP do sistema, será possível executar curl ifconfig.co.

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: allowlist
    spec:
      applyOnForward: true
      preDNAT: true
      ingress:
      - action: Allow
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: TCP
        source:
          nets:
          - <client_address>/32
      selector: ibm.role=='worker_public'
      order: 500
      types:
      - Ingress
    
  5. Aplique a política.

    • Linux:

      calicoctl apply -f filepath/allowlist.yaml
      
    • Windows e OS X:

      calicoctl apply -f filepath/allowlist.yaml --config=filepath/calicoctl.cfg
      

    O endereço IP do seu sistema agora é permitido.

  6. Usando o valor de sua folha de dicas, verifique se agora é possível acessar o endereço IP do NLB público.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    
  7. Se tiver acesso a outro sistema que tenha um endereço IP diferente, tente acessar o NLB por esse sistema.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    

    A conexão atinge o tempo limite porque o endereço IP desse sistema não é permitido.

Neste ponto, todo o tráfego para as portas de nó públicas e o NLB está bloqueado. Apenas o tráfego do IP do sistema permitido é permitido.

Negar o tráfego de entrada de IPs específicos para o NLB

Na lição anterior, você bloqueou todo o tráfego e permitiu apenas alguns IPs. Esse cenário funciona bem para propósitos de teste quando você deseja limitar o acesso a somente alguns endereços IP de origem controlada. No entanto, a firma PR tem apps que precisam estar amplamente disponíveis para o público. É necessário certificar-se de que todo o tráfego seja permitido, exceto o tráfego incomum que você está vendo de alguns endereços IP. Uma lista de bloqueio é útil em um cenário como este porque ela pode ajudá-lo a evitar um ataque de um pequeno conjunto de endereços IP.

Nesta lição, bloqueie o tráfego do endereço IP de origem do seu próprio sistema. No final da Lição 4, todo o tráfego para as portas do nó público está bloqueado e todo o tráfego para o NLB público é permitido. Apenas o tráfego do IP do seu sistema específico para o NLB é bloqueado.

  1. Limpe as políticas da lista de permissões criadas na lição anterior.

    • Linux:
      calicoctl delete GlobalNetworkPolicy deny-lb-port-80
      
      calicoctl delete GlobalNetworkPolicy allowlist
      
    • Windows e OS X:
      calicoctl delete GlobalNetworkPolicy deny-lb-port-80 --config=filepath/calicoctl.cfg
      
      calicoctl delete GlobalNetworkPolicy allowlist --config=filepath/calicoctl.cfg
      

    Agora, todo o tráfego TCP e UDP recebido de qualquer IP de origem para o endereço IP e a porta do NLB é permitido novamente.

  2. Para negar todo o tráfego TCP e UDP recebido do endereço IP de origem do seu sistema para o endereço IP e a porta do NLB, crie uma política pré-DNAT de baixa ordem chamada blocklist.yaml em um editor de texto. Usando os valores da folha de dicas, substitua <loadbalancer_IP> pelo endereço IP público do NLB e <client_address> pelo endereço IP público do IP de origem do sistema.

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: blocklist
    spec:
      applyOnForward: true
      preDNAT: true
      ingress:
      - action: Deny
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: TCP
        source:
          nets:
          - <client_address>/32
      - action: Deny
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: UDP
        source:
          nets:
          - <client_address>/32
     selector: ibm.role=='worker_public'
     order: 500
     types:
     - Ingress
    
  3. Aplique a política.

    • Linux:

      calicoctl apply -f filepath/blocklist.yaml
      
    • Windows e OS X:

      calicoctl apply -f filepath/blocklist.yaml --config=filepath/calicoctl.cfg
      

    O endereço IP do seu sistema agora está bloqueado.

  4. Usando o valor de sua folha de dicas, verifique no sistema se não é possível acessar o IP do NLB porque o IP do seu sistema está bloqueado.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    

    Neste ponto, todo o tráfego para as portas de nó públicas está bloqueado e todo o tráfego para o NLB público está permitido. Apenas o tráfego do IP do seu sistema específico para o NLB é bloqueado.

Ótimo trabalho! Você controlou com sucesso o tráfego para o seu app usando políticas pré-DNAT do Calico para bloquear IPs de origem.

Registrando o tráfego bloqueado de IPs específicos para o NLB

Na lição anterior, você bloqueou o tráfego do IP do seu sistema para o NLB. Nesta lição, será possível aprender como registrar as solicitações de tráfego negado.

Neste exemplo, a empresa de relações públicas para a qual você trabalha quer que você configure uma trilha de registro para qualquer tráfego incomum que esteja sendo continuamente negado por uma de suas políticas de rede. Para monitorar a potencial ameaça de segurança, configure a criação de log para registrar toda vez que a política de lista de bloqueios negar uma tentativa de ação no IP do NLB.

  1. Crie uma NetworkPolicy do Calico chamada log-denied-packets. Essa política de log usa o mesmo seletor que a política blocklist, que inclui essa política na cadeia de regras Iptables do Calico. Usando um número de ordem mais baixa, como 300, é possível assegurar que essa regra seja incluída na cadeia de regras Iptables antes da política de lista de bloqueios. Os pacotes do seu IP são registrados por essa política antes de tentarem corresponder à regra de política blocklist e são negados.

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
        name: log-denied-packets
     spec:
      applyOnForward: true
      preDNAT: true
      ingress:
      - action: Log
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: TCP
        source:
          nets:
          - <client_address>/32
      - action: Log
        destination:
          nets:
          - <loadbalancer_IP>/32
          ports:
          - 80
        protocol: UDP
        source:
          nets:
          - <client_address>/32
      selector: ibm.role=='worker_public'
      order: 300
      types:
      - Ingress
    
  2. Aplique a política.

    • Linux:

      calicoctl apply -f /log-denied-packets.yaml
      
    • Windows e OS X:

      calicoctl apply -f /log-denied-packets.yaml --config=<filepath>/calicoctl.cfg
      
  3. Gere entradas de log enviando solicitações do IP de seu sistema para o IP do NLB. Esses pacotes de solicitações são registrados antes de serem negados.

    curl --connect-timeout 10 <loadbalancer_IP>:80
    
  4. Verifique as entradas de log que são gravadas no caminho /var/log/syslog. A entrada de log é semelhante à seguinte.

    Sep 5 14:34:40 <worker_hostname> kernel: [158271.044316] calico-packet: IN=eth1 OUT= MAC=08:00:27:d5:4e:57:0a:00:27:00:00:00:08:00 SRC=192.XXX.XX.X DST=192.XXX.XX.XX LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=52866 DF PROTO=TCP SPT=42962 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0
    

Legal! Configure a criação de log para que o tráfego bloqueado possa ser monitorado com mais facilidade.

Para limpar a lista de bloqueios e as políticas de log:

  1. Limpe a política de lista de bloqueios.
    • Linux:
      calicoctl delete GlobalNetworkPolicy blocklist
      
    • Windows e OS X:
      calicoctl delete GlobalNetworkPolicy blocklist --config=filepath/calicoctl.cfg
      
  2. Limpe a política de log.
    • Linux:
      calicoctl delete GlobalNetworkPolicy log-denied-packets
      
    • Windows e OS X:
      calicoctl delete GlobalNetworkPolicy log-denied-packets --config=filepath/calicoctl.cfg
      

O que vem a seguir?