Capacidade de ligação de rede com o systemd

2

Estou implantando o Goldfish , uma interface para Vault , em produção em um servidor dedicado ao gerenciamento de segredos. Então a segurança é uma das principais preocupações aqui.

Estou tentando implantar o serviço com systemd em um sistema UnBuntu 16.04, dando-lhe o mínimo de permissões possíveis. Eu quero que ele seja executado como o usuário não-root goldfish e para escutar na porta 443. Eu tentei várias opções.

Solução 1: usando um soquete systemd , como sugerido em várias postagens que encontrei, como este (o backend Goldfish é escrito em Go como no post). Isso parece ser o mais preciso e seguro, pois é gerenciado inteiramente pelo systemd e abre uma única porta para um único serviço. Os arquivos da minha unidade são assim:

  • /etc/systemd/system/goldfish.socket :

    [Unit]
    Description=a Vault interface
    
    [Socket]
    ListenStream=443
    NoDelay=true  # Tried with false as well
    
  • /etc/systemd/system/goldfish.service :

    [Unit]
    Description=a Vault interface
    After=vault.service
    Requires=goldfish.socket
    ConditionFileNotEmpty=/etc/goldfish.hcl
    
    [Service]
    User=goldfish
    Group=goldfish
    ExecStart=/usr/local/bin/goldfish -config=/etc/goldfish.hcl
    NonBlocking=true  # Tried with false as well
    
    [Install]
    WantedBy=multi-user.target
    

Infelizmente, recebo um "listen tcp 0.0.0.0:443: bind: permission denied". Portanto, parece que ainda não obtém a permissão desejada, o que parece frustrar o propósito de criar um soquete para o serviço. O que estou perdendo aqui?

Solução 2: fornecendo o recurso CAP_NET_BIND_SERVICE ao serviço. Desta vez, não uso nenhum soquete systemd, mas a configuração AmbientCapabilities no serviço (também tentei com CpabilityBoudingSet e Capabilities , o sendo esta última surpreendentemente não documentada em systemd.exec ). Adicionar o recurso CAP_NET_BIND_SERVICE ao serviço deve dar ao serviço o direito de ligar-se a qualquer porta privilegiada.

  • /etc/systemd/system/goldfish.service :

    [Service]
    User=goldfish
    Group=goldfish
    ExecStart=/usr/local/bin/goldfish -config=/etc/goldfish.hcl
    
    # Tried combinations of those:
    AmbientCapabilities=CAP_NET_BIND_SERVICE
    #CapabilityBoundingSet=CAP_NET_BIND_SERVICE
    #Capabilities=CAP_NET_BIND_SERVICE+ep
    

Ainda sem sorte, sempre acabo com "listen tcp 0.0.0.0:443: bind: permission denied". O que estou perdendo sobre gerenciamento de recursos com o systemd?

Solução 3: dando o recurso CAP_NET_BIND_SERVICE para o executável. Desta vez eu dou o recurso CAP_NET_BIND_SERVICE diretamente ao executável goldfish, e nada no serviço systemd:

sudo setcap cap_net_bind_service=+ep /usr/local/bin/goldfish

Hurray, funciona! O serviço liga-se corretamente à porta 443 e eu posso usá-lo. No entanto, agora eu tenho um binário que pode ser executado por qualquer usuário e vincular a qualquer porta privilegiada, que eu realmente não gosto. Qual é o relacionamento entre os recursos executáveis e os recursos de serviço do systemd? Não deveria permitir alcançar o mesmo resultado que eu recebo aqui, mas apenas para um processo específico?

Solução 4: colocando o serviço atrás de um proxy. A solução que estou considerando agora é colocar o Goldfish atrás de um proxy nginx que será o único visível do lado de fora e escutando na porta 443 Isso parece ser um bom compromisso, pois mantém permissões restritas, mas adiciona uma nova peça à configuração, com o que acrescenta de complexidade e potencial de erro. Parece uma opção superior ou menor em termos de segurança e administração do sistema?

Portanto, tenho várias perguntas aqui, mas todas relacionadas a fazer um serviço systemd ser executado como um usuário não privilegiado enquanto ouve em uma porta privilegiada e as implicações de segurança que ele possui. Alguém já encontrou os mesmos problemas?

Obrigado pela sua ajuda!

    
por Macfli 15.06.2018 / 11:28

1 resposta

0

Eu sei que isso não é exatamente o que você queria e adiciona "outra peça" ao quebra-cabeça, mas você poderia considerar criar um arquivo systemd .service e mover a porta de escuta de aplicativos para > 1023 (isso permite que não-raiz se ligue para isso), em seguida, crie uma regra iptables que redireciona todo o tráfego da porta 443 para a nova porta personalizada como esta:

iptables -t nat -A PREROUTING -i <incoming_interface> -p tcp --dport 443 -j REDIRECT --to-port 8443

Neste exemplo, todo o tráfego tcp para a porta 443 seria redirecionado de forma transparente para a porta 8443.

    
por 16.06.2018 / 11:15