Skip to content

Security: loosebird/flock-vpn

Security

docs/security.md

Exatamente isso. O seu aplicativo será o cérebro (UI e lógica) e o ZeroTier rodando via CLI no sistema será o motor (daemon). A comunicação via HTTP garante que você tenha respostas estruturadas em JSON.

O desafio do authtoken.secret é um obstáculo clássico de arquitetura de segurança multiplataforma. Como você não quer (e não deve) rodar a interface gráfica inteira do seu app como Administrador/Root o tempo todo por questões de segurança, você precisa de um método para buscar essa chave restrita de forma isolada.

A solução padrão e mais segura para esse cenário é a Elevação de Privilégio Sob Demanda.

Em vez de alterar as permissões do sistema operacional ou criar instaladores complexos, o seu aplicativo roda normalmente no espaço do usuário e pede a senha de administrador apenas uma vez para ler o arquivo e fazer uma cópia segura para a pasta local do seu app.

Aqui está o fluxo exato de como você implementa isso no Python:

O Fluxo de Autorização

  1. Tentativa Silenciosa: Quando o app abre, o Python tenta ler o caminho oficial do authtoken.secret.
  2. Captura do Erro: Se o Python estourar um PermissionError (o que vai acontecer na primeira execução), a sua UI no Slint exibe um aviso: "O aplicativo precisa de autorização para acessar o serviço de rede", junto com um botão de "Autorizar".
  3. Elevação e Leitura: Ao clicar no botão, o Python dispara um comando nativo do sistema operacional pedindo a senha. O comando roda em modo elevado, lê o arquivo original e salva o conteúdo na pasta do seu usuário (ex: ~/.config/flock-vpn/zt_token.txt).
  4. Proteção da Cópia: O Python aplica permissões estritas a essa cópia (chmod 600 no Linux/Mac) para que nenhum outro usuário da máquina consiga ler.
  5. Conexão: O seu app passa a usar essa cópia local para enviar os cabeçalhos HTTP para a porta 9993 nas próximas vezes que for aberto, sem nunca mais pedir a senha.

Os Comandos Nativos (Cross-Platform)

No seu código Python, a função atrelada ao botão "Autorizar" precisará identificar o sistema operacional e rodar o comando específico para invocar a janela nativa de senha de cada plataforma. Você pode executar esses comandos usando a biblioteca subprocess do Python.

Para macOS (Seu ambiente de trabalho primário): O macOS possui o osascript, que invoca a janela nativa de credenciais do sistema e retorna a saída do comando via terminal.

# O caminho no Mac é: /Library/Application Support/ZeroTier/One/authtoken.secret
comando_mac = 'osascript -e \'do shell script "cat \\"/Library/Application Support/ZeroTier/One/authtoken.secret\\"" with administrator privileges\''

Para Linux: No ecossistema Linux, utilizamos o pkexec (PolicyKit). Ele é o padrão moderno em ambientes Wayland/X11 (incluindo o COSMIC no Fedora) para gerar a janela gráfica de senha (polkit-agent) quando um comando de terminal precisa de root.

# O caminho no Linux é: /var/lib/zerotier-one/authtoken.secret
comando_linux = ['pkexec', 'cat', '/var/lib/zerotier-one/authtoken.secret']

Para Windows: No Windows, invocamos o PowerShell com o verbo RunAs, que aciona a tela do UAC (User Account Control). Como o comando roda em uma janela separada, pedimos para ele ler o arquivo restrito e despejar o conteúdo em um arquivo de texto na pasta %APPDATA% do usuário.

# O caminho no Windows é: C:\ProgramData\ZeroTier\One\authtoken.secret
caminho_destino = os.path.expandvars(r"%APPDATA%\FlockVPN\token.txt")
comando_win = [
    "powershell", 
    "Start-Process", "powershell", 
    f"-ArgumentList '-Command Get-Content C:\\ProgramData\\ZeroTier\\One\\authtoken.secret > {caminho_destino}'", 
    "-Verb", "RunAs", "-WindowStyle", "Hidden"
]

Dessa forma, o seu código continua operando com o princípio do menor privilégio. O executável principal é seguro, os usuários não precisam abrir o terminal em momento algum, e você obtém a chave exata para iniciar as requisições HTTP locais da forma recomendada pela documentação do ZeroTier.

There aren't any published security advisories