Linux

Roteador Linux - Parte 3 - Usuários, Segurança e Firewall

Esta é a terceira parte de uma série de artigos descrevendo como construir seu próprio roteador Linux.

Na primeira e segunda partes, instalamos o sistema operacional, configuramos a rede e configuramos o Mac Mini para funcionar como um roteador.
Nesta parte, aumentaremos a segurança criando usuários, alterando a autenticação SSH e reforçando a configuração do firewall.

Fire of wall
EAA AirVenture Oshkosh 2013 Wall of Fire

Tabela de Conteúdos

Usuários

Crie os usuários desejados. Você pode criar qualquer usuário que precisar. No meu caso, criarei três: um para atuar como usuário administrador chamado admin, outro para os contêineres rootless como podman, e um último chamado git para ter um repositório Git pessoal e privado.

Para o usuário podman, se estiver utilizando o modo de armazenamento não permanente, você precisa alocar os subuid e subgid para o usuário de forma estática.

1. Gerar Senha Criptografada (opcional)

Este passo é opcional, já que a única forma para se autenticar no servidor será via SSH usando Chaves SSH, mas você pode criar uma senha se quiser que ela seja solicitada ao usar sudo ou ao autenticar localmente.

Crie as senhas para seus usuários:

mkpasswd --method=SHA-512
Password: #Digite a senha (hackme00)
$6$ZeLsWXraGkrm9IDL$Y0eTIK4lQm8D0Kj7tSVzdTJ/VbPKea4ZPf0YaJR68Uz4MWCbG1EJp2YBOfWHNSZprZpjpbUvCIozbkr8yPNM0.

2. Chaves SSH

Gere um par de chaves privadas e públicas ou use uma já existente. Maiores detalhes neste artigo do GitHub.

Siga os passos abaixo para gerar a chave SSH no seu computador:

ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/router-admin  
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase): 
Enter the same passphrase again: 
Your identification has been saved in /root/.ssh/router-admin
Your public key has been saved in /root/.ssh/router-admin.pub
The key fingerprint is...

Recupere sua chave pública SSH e copie o conteúdo:

cat ~/.ssh/router-admin.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... [email protected]

Mantenha sua chave privada em segurança e não a compartilhe com ninguém.

Repita o mesmo processo para cada usuário que você deseja criar.

3. Criar o arquivo `users.nix` em `/etc/nixos/modules/`

Acesse o servidor via SSH usando o usuário root e a senha definida durante a instalação na parte 1 deste tutorial e faça o seguinte:

Defina os usuários desejados substituindo os valores de openssh.authorizedKeys.keys. No exemplo, a chave para o usuário admin deve ser preenchida com o valor de ~/.ssh/router-admin.pub.

/etc/nixos/modules/users.nix

{ config, pkgs, ... }: {
  users.users.root.initialHashedPassword = "##HashedPa$$word"; # Você pode remover esta linha se não quiser fazer login diretamente como root.
  users.users = {
    # Usuário Admin
    admin = {
      uid = 1000;
      isNormalUser = true;
      description = "Usuário Administrador";
      home = "/home/admin"; # Diretório home
      extraGroups = [ "wheel" ]; # Adicione o usuário ao grupo 'wheel' para acesso sudo
      initialHashedPassword = "$6$rounds=656000$example$hashedpassword"; # Senha, opcional
      openssh.authorizedKeys.keys = [
        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC..."  # Substitua pela chave pública real
      ];
    };

    # Usuário Podman para containers podman rootless
    podman = {
      uid = 1001;
      subUidRanges = [{ startUid = 100000; count = 65536; }];
      subGidRanges = [{ startGid = 100000; count = 65536; }];
      isNormalUser = true;
      description = "Podman Rootless";
      home = "/home/podman";
      group = "containers";
      openssh.authorizedKeys.keys = [
        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC..."  # Substitua pela chave pública real
      ];
      linger = true; # Lingering permite que serviços de usuário systemd iniciem sem necessidade de login.
    };

    # Usuário Git
    git = {
      uid = 1002;
      isNormalUser = true;
      description = "Git";
      home = "/home/git";
      openssh.authorizedKeys.keys = [
        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC..."  # Substitua pela chave pública real
      ];
    };
  };
  users.groups.containers = {
    gid = 993;
    members = [ "podman" ];
  }

  # Habilitar sudo para usuários no grupo 'wheel'
  security.sudo = {
    enable = true;
    wheelNeedsPassword = false;  # Opcional: Requer que uma senha seja inserida para o comando sudo. Defina como true se optar por criar o usuário admin com senha.
  };
}

4. Desativar autenticação por senha via SSH

Desative a autenticação por senha e o login de root via SSH.

/etc/nixos/modules/services.nix

  services = { 
  ...
    openssh = {
      enable = true;
      settings.PermitRootLogin = "no"; # Era "yes". Altere para "no" para desativar
      settings.PasswordAuthentication = false;
    };
  ...
  };

5. Atualizar a configuração e tentar fazer login

Reconstrua a configuração:

nixos-rebuild switch

Tente fazer login no servidor usando o admin com a chave privada gerada anteriormente.

ssh -i ~/.ssh/router-admin [email protected]

6. Criar configuração para acesso SSH

Se você não quiser digitar ssh -i ~/.ssh/router-admin [email protected] toda vez para se autenticar no servidor, no seu computaor, configure o arquivo ~/.ssh/config da seguinte forma:

Host router-admin
  Hostname 10.1.78.1
  user admin
  IdentityFile ~/.ssh/router-admin

Host router-podman
  Hostname 10.1.78.1
  user podman
  IdentityFile ~/.ssh/router-podman

Host router-git
  Hostname 10.1.78.1
  user git
  IdentityFile ~/.ssh/router-git

Tente acessar o servidor via ssh sem fornecer o arquivo de identidade como parâmetro.

ssh router-admin

7. Bloquear a conta root (opcional)

Como o serviço SSH está configurado para impedir logins de root, não vejo necessidade de bloquear a conta root localmente, mas você pode fazer isso se quiser.
Se você configurou seu servidor com armazenamento não permanente, basta apenas remover a linha users.users.root.initialHashedPassword = "##HashedPa$$word" do arquivo users.nix para desativar a senha do root sem etapas adicionais.

ATENÇÃO Esteja ciente de que bloquear a senha do root sem uma senha configurada para a conta admin, o impedirá autênticar-se no servidor localmente, permitindo apenas via SSH. Certifique-se também de ter criado a conta admin e adicionado-a ao grupo wheel.

passwd -l root

Firewall

Com as configurações do usuário concluídas, é hora de melhorar a segurança do nosso firewall.

Configuração Atual

Até agora, nossa configuração de firewall inclui:

  • Permitir todo o tráfego de entrada da rede LAN.
  • Bloquear todo o tráfego de entrada das redes WAN/PPPoE, Guest e IoT, exceto para acesso à internet.

Embora essa configuração forneça um nível básico de segurança, podemos alcançar uma proteção melhor por meio de um controle mais granular do tráfego. Isso garante que, se algum serviço abrir portas adicionais no servidor de forma não intencional, o tráfego não autorizado não será permitido.

Melhorias Planejadas

Vamos refinar nosso firewall para permitir apenas o tráfego necessário para cada rede:

  • LAN: Permitir os serviços DHCP e SSH.
  • Guest e IoT: Permitir apenas o serviço DHCP.
  • WAN: Habilitar SSH para acesso remoto.

Organizando a Configuração do Firewall

Para simplificar o gerenciamento e garantir escalabilidade, estruturaremos a configuração do firewall em seções lógicas. Essa abordagem divide as interfaces, regras e serviços em zonas e organiza a configuração em vários arquivos. A estrutura será a seguinte:

**Tabela INET** (Regras principais do firewall)

  • sets.nft: Mapeia interfaces para suas respectivas zonas.
  • services.nft: Define cadeias para portas de serviços, como SSH e HTTP.
  • zones.nft: Especifica quais serviços são permitidos em cada zona.
  • rules.nft: Configura as regras para zonas e gerencia o fluxo de tráfego.

**Tabela NAT** (Regras de Tradução de Endereços de Rede)

  • nat_sets.nft: Mapeia interfaces para suas respectivas zonas.
  • nat_chains.nft: Define cadeias NAT para tarefas como redirecionamento de portas.
  • nat_zones.nft: Associa cadeias NAT às zonas.
  • nat_rules.nft: Configura regras NAT para zonas.

Essa abordagem modular tornará a configuração do firewall mais organizada, fácil de entender e simples de manter ou estender no futuro.

Configuração dos Arquivos

1. Remova o arquivo `nftables.nft`

Como dividiremos o nftables em arquivos separados, não será mais necessário usar este arquivo. Você pode deletá-lo ou apenas deixá-lo inativo.

rm /etc/nixos/modules/nftables.nft

2. Crie os Arquivos de Configuração do NFTables

Crie o diretório e todos os arquivos necessários para o NFTables.

mkdir -p /etc/nixos/nftables
touch /etc/nixos/nftables/{nat_chains,nat_rules,nat_sets,nat_zones,rules,services,sets,zones}.nft

Configure cada arquivo NFTables conforme necessário.

sets.nft

Utilizaremos variáveis para atribuir dinamicamente os valores das interfaces.

cat << EOF > /etc/nixos/nftables/sets.nft 
table inet filter {
  set WAN {
    type ifname;
    elements = { \$if_wan }
  }

  set LAN {
    type ifname;
    elements = { \$if_lan }
  }

  set GUEST {
    type ifname;
    elements = { \$if_guest }
  }

  set IOT {
    type ifname;
    elements = { \$if_iot }
  }
}
EOF
services.nft
cat << EOF > /etc/nixos/nftables/services.nft
table inet filter {
  chain dhcp_input {
    udp dport 67 ct state { new, established } counter accept comment "Permitir DHCP"
  }

  chain echo_input {
    icmp type echo-request accept
    icmp type echo-reply accept
  }

  chain public_ssh_input {
    tcp dport ssh ct state { new, established } limit rate 10/minute burst 50 packets counter accept comment "Permitir tráfego SSH com limite de retentativas"
  }

  chain ssh_input {
    tcp dport ssh ct state { new, established } counter accept comment "Permitir SSH"
  }
}
EOF 
zones.nft
cat << EOF > /etc/nixos/nftables/zones.nft
table inet filter {
  chain LAN_INPUT {
    jump dhcp_input
    jump echo_input
    jump ssh_input
  }

  chain GUEST_INPUT {
    jump dhcp_input
    jump echo_input
  }

  chain IOT_INPUT {
    jump dhcp_input
    jump echo_input
  }

  chain WAN_INPUT {
    jump public_ssh_input
  }
}
EOF 
rules.nft
cat << EOF > /etc/nixos/nftables/rules.nft
table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    iifname "lo" counter accept

    iifname @LAN jump LAN_INPUT 
    iifname @GUEST jump GUEST_INPUT
    iifname @IOT jump IOT_INPUT
    iifname @WAN jump WAN_INPUT
 
  
    # Permitir tráfego de retorno da ppp0 e descartar todo o resto
    iifname @LAN ct state { established, related } counter accept
    iifname @WAN ct state { established, related } counter accept
  }

  chain output {
    type filter hook output priority 100; policy accept;
  }

  chain forward {
    type filter hook forward priority filter; policy drop;
    iifname @LAN  oifname @WAN counter accept comment "Permitir trafego confiável LAN para WAN"
    iifname @WAN oifname @LAN ct state established,related counter accept comment "Permitir tráfego estabelecido de volta para LANs"
    
    iifname @GUEST  oifname @WAN counter accept comment "Permitir trafego confiável de GUEST para WAN"
    iifname @WAN oifname @GUEST ct state established,related counter accept comment "Permitir tráfego estabelecido de volta para GUEST"
  
    iifname @IOT  oifname @WAN counter accept comment "Permitir tráfego confiável de IOT para WAN"
    iifname @WAN oifname @IOT ct state established,related counter accept comment "Permitir tráfego estabelecido de volta para IOT"

    # Bloquear tráfego entre redes
    iifname @GUEST oifname @LAN drop comment "Bloquear conexões de GUEST para LAN"
    iifname @IOT oifname @LAN drop comment "Bloquear conexões de IOT para LAN"
    iifname @GUEST oifname @IOT drop comment "Bloquear conexões de GUEST para IOT"
    iifname @IOT oifname @GUEST drop comment "Bloquear conexões de IOT para GUEST"
    
    # MSS Clamp
    oifname @WAN tcp flags syn tcp option maxseg size set 1452
  }
}
EOF 
nat_sets.nft
cat << EOF > /etc/nixos/nftables/nat_sets.nft
table nat {
  set WAN {
    type ifname;
    elements = { \$if_wan }
  }

  set LAN {
    type ifname;
    elements = { \$if_lan }
  }

  set GUEST {
    type ifname;
    elements = { \$if_guest }
  }

  set IOT {
    type ifname;
    elements = { \$if_iot }
  }
}
EOF
nat_chains.nft

As cadeias NAT serão criadas vazias por enquanto.

cat << EOF > /etc/nixos/nftables/nat_chains.nft 
table ip nat {
}
EOF
nat_zones.nft

Como não há cadeias de redirecionamento, as zonas NAT serão criadas com cadeias vazias por enquanto.

cat << EOF > /etc/nixos/nftables/nat_zones.nft
table ip nat {
  chain LAN_PREROUTING {
  }

  chain GUEST_PREROUTING {
  }

  chain IOT_PREROUTING {
  }

  chain WAN_PREROUTING {
  }
}
EOF
nat_rules.nft
cat << EOF > /etc/nixos/nftables/nat_rules.nft
table ip nat {
  chain prerouting {
    type nat hook prerouting priority filter; policy accept;
    iifname @LAN jump LAN_PREROUTING 
    iifname @GUEST jump GUEST_PREROUTING 
    iifname @IOT jump IOT_PREROUTING 
    iifname @WAN jump WAN_PREROUTING 
  }

  chain postrouting {
    type nat hook postrouting priority filter; policy accept;
    oifname @WAN tcp flags syn tcp option maxseg size set 1452
    oifname @WAN masquerade
  }
}
EOF

3. Atualize o arquivo de configuração networking.nix

Edite a seção network do arquivo de configuração networking.nix como a seguir:
Atualize apenas a seção networking. Deixe o restante do arquivo como está.

/etc/nixos/modules/networking.nix

...
  networking = {
    useDHCP = false;
    firewall.enable = false;
    nftables = {
      enable = true;
      rulesetFile = pkgs.writeText "ruleset.conf" ''
        define if_wan = "ppp0"
        define if_lan = "${lan}"
        define if_guest = "${guest}"
        define if_iot =  "${iot}"
        define ip_lan = "${ip_lan}"
        define ip_guest = "${ip_guest}"
        define ip_iot = "${ip_iot}"
        
        # Inet filter, serviços e regras
        include "${../nftables/sets.nft}"
        include "${../nftables/services.nft}"
        include "${../nftables/zones.nft}"
        include "${../nftables/rules.nft}"

        # Nat & redirecionamento
        include "${../nftables/nat_sets.nft}"
        include "${../nftables/nat_chains.nft}"
        include "${../nftables/nat_zones.nft}"
        include "${../nftables/nat_rules.nft}"
      '';
      flattenRulesetFile = true;
    };
  };
...

4. Reconstrua a configuração e teste

nixos-rebuild switch

Conclusão

Com esta configuração, melhoramos a segurança deste firewall. O que foi feito até agora:

  • Reduzimos a necessidade de usar a conta root para certas tarefas.
  • Dividimos nosso firewall em zonas, tornando-o mais fácil de gerenciar.
  • Criamos um controle mais granular sobre o tráfego em nosso servidor.

Na próxima parte, é hora de instalar o Podman e configurar nosso Servidor DNS com o Unbound.

keywords: macmini • roteador • linux • nixos • pppoe • unifi • ubiquiti • apple • vlan • tl-sg108e

This article in other languages