- Go 98.2%
- Makefile 1.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The client now sends fixed-size batches every 10 ms (--tick, 0 disables) so network observers cannot infer typing rhythm. The server caps unauthenticated connections at 2 per IP and 32 total, with a 5 second authentication window. Adds tests for rejected TLS 1.2, missing client certificate, revoked peers, batch sizing and fuzz targets for pair codes and frames. Bumps version to 1.1.0. |
||
| .gitignore | ||
| .version | ||
| connect.go | ||
| go.mod | ||
| go.sum | ||
| identity.go | ||
| inject_linux.go | ||
| inject_linux_test.go | ||
| inject_other.go | ||
| listen.go | ||
| main.go | ||
| Makefile | ||
| proto.go | ||
| README.md | ||
| rk_test.go | ||
rk: teclado remoto pela LAN
rk transforma uma máquina em teclado de outra pela rede local. Você digita numa janela no seu computador e as teclas aparecem onde estiver o cursor na outra máquina, como se houvesse um teclado USB plugado nela.
- alvo: a máquina que recebe e digita as teclas. Roda
rk listen. Só Linux (X11, Wayland e console de texto). - teclado: a máquina onde você está. Roda
rk connect, que abre uma janela; enquanto ela tiver foco, toda tecla vai para o alvo. Linux, macOS e Windows, sem permissão de administrador.
A conexão usa TLS 1.3 com autenticação mútua: o alvo só aceita teclados pareados e o teclado só conecta em alvos pareados.
Compilação
Requer Go 1.27 ou mais novo. Não usa cgo: qualquer máquina compila para todos os sistemas.
make build # ./rk para o sistema atual
make dist # dist/rk-<so>-<arquitetura> para Linux, macOS e Windows (amd64 e arm64)
make test # go vet + testes com detector de corrida
make clean # remove ./rk e dist/
A versão fica no arquivo .version e é embutida no binário na compilação (rk version mostra).
Preparar o alvo (Linux, uma vez, como root)
O rk digita por um teclado virtual do kernel (/dev/uinput). Libere o acesso para o seu usuário:
echo 'KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"' > /etc/udev/rules.d/99-rk.rules
udevadm control --reload-rules && udevadm trigger /dev/uinput
usermod -aG input SEU_USUARIO
Faça logout e login para o grupo valer. Se faltar esse passo, rk listen mostra esses mesmos comandos.
Abra a porta 7277/TCP no firewall do alvo:
firewall-cmd --add-port=7277/tcp --permanent && firewall-cmd --reload # Fedora, RHEL
ufw allow 7277/tcp # Ubuntu, Debian
Uso
1. Parear (uma vez por teclado)
No alvo:
rk listen --pair
Ele mostra um código como 7KQX-M2PA-..., válido por 2 minutos e com no máximo 3 tentativas. No teclado:
rk pair 192.168.0.10 7KQX-M2PA-...
O código prova a identidade dos dois lados: o teclado confere que está falando com o alvo certo e o alvo confere que o código veio de quem está na frente dele. O alvo continua rodando depois do pareamento, pronto para a sessão.
2. Digitar
No alvo, se ainda não estiver rodando:
rk listen
No teclado:
rk connect 192.168.0.10
A janela mostra o estado da conexão em texto, com uma bolinha verde (conectado, com a latência), amarela (conectando) ou vermelha (sem conexão, com o motivo). A reconexão é automática.
Para sair: feche a janela, aperte Ctrl+Alt+Shift+Esc com a janela em foco, ou Ctrl+C no terminal.
Gerenciar teclados pareados (no alvo)
rk clients # lista
rk clients rm 3fa9c1d2 # revoga pelo início do fingerprint (mínimo 8 caracteres)
A revogação vale para a próxima conexão, sem reiniciar o rk listen.
Opções
| Comando | Opção | Padrão | Uso |
|---|---|---|---|
rk listen |
--addr |
:7277 |
endereço e porta de escuta |
rk listen |
--pair |
desligado | aceita um novo teclado com código de uso único |
rk connect |
--tick |
10ms |
ritmo do fluxo constante que esconde a digitação (veja Segurança); 0 desliga e envia cada tecla na hora |
rk connect |
--ping |
1s |
intervalo de ping (latência mostrada na janela); com --tick 0, 100ms evita picos de latência por economia de energia do Wi-Fi |
As opções vêm antes do endereço: rk connect --tick 0 192.168.0.10. A porta é opcional (host:porta).
Comportamento
- Teclas físicas, layout do alvo. O
rkenvia a posição da tecla, não o caractere. Quem decide o caractere é o layout do alvo, como num teclado USB. Teclas mortas (´ ~ ^), Compose e atalhos funcionam no alvo. Se os dois forem ABNT2, tudo bate; se o teclado for US e o alvo ABNT2, a tecla;viraç. - Atalhos do sistema. Com a janela em foco, Alt+Tab e a tecla Windows/Super vão para o alvo (Windows, X11 e Wayland; no GNOME aparece uma confirmação na primeira vez). No macOS, Cmd+Tab, Cmd+Espaço e Ctrl+setas continuam agindo no Mac. No Windows, Ctrl+Alt+Del e Win+L nunca são capturados.
- Teclas presas. Ao perder o foco, fechar a janela ou cair a conexão, todas as teclas são soltas no alvo. Se o alvo ficar 3 segundos sem notícia do teclado, ele solta tudo e encerra a sessão.
- Uma sessão por vez. Um segundo teclado que conecta derruba o primeiro.
- Caps Lock e Num Lock valem no alvo; a luz do teclado local pode ficar diferente.
- Tela de bloqueio. O teclado virtual do kernel alcança a tela de bloqueio e o console do alvo: dá para digitar a senha de desbloqueio remotamente.
Segurança
Quem conecta no alvo ganha um teclado nele, então o rk trata a conexão como acesso total à máquina.
- Criptografia só da biblioteca padrão do Go. TLS 1.3 obrigatório nos dois lados (TLS 1.2 é recusado), chaves Ed25519, troca de chaves híbrida pós-quântica (X25519MLKEM768). Não há modo sem criptografia.
- Autenticação mútua por fingerprint. O alvo exige certificado de cliente e só aceita os de
authorized.json; o teclado só aceita alvos deknown.json. O TLS 1.3 obriga cada lado a provar que tem a chave privada. - Pareamento. O código de 26 caracteres contém 80 bits do fingerprint do alvo (o teclado detecta um intermediário falso) e 48 bits de segredo (3 tentativas, 2 minutos, uso único). Confira no log do alvo a linha
pareado: <nome>: se aparecer um nome que não é o seu, alguém viu o código antes; revogue comrk clients rm. - Ritmo de digitação escondido. Por padrão o teclado envia um pacote de tamanho fixo a cada 10 ms, com ou sem teclas. Quem observa a rede vê um fluxo constante (cerca de 100 pacotes por segundo, uns 10 KB/s) e não descobre quando, nem quantas, teclas foram digitadas. O custo é até 10 ms de latência a mais.
--tick 0desliga. - Limite de conexões não autenticadas. No máximo 2 por IP e 32 no total, com 5 segundos para autenticar; acima disso o alvo fecha a conexão na hora.
Limites conhecidos:
identity.pemguarda a chave privada sem senha (como uma chave SSH sem passphrase). Quem ler o arquivo se passa pela máquina: nesse caso revogue o fingerprint no alvo e apague o arquivo para gerar outro.- O início e o fim de cada sessão continuam visíveis na rede.
- Errar o código 3 vezes de propósito invalida o pareamento em andamento. Isso só atrapalha (basta gerar outro código), não dá acesso.
macOS e Windows (teclado)
Nenhuma permissão de administrador é necessária. Como o binário não é assinado com certificado da Apple nem da Microsoft:
-
macOS: use
rk-darwin-arm64em Macs com Apple Silicon (M1 em diante) erk-darwin-amd64em Macs Intel. Arquivos baixados pelo navegador, AirDrop ou mensageiros recebem a marca de quarentena, e o Gatekeeper recusa o binário com "O item não foi aberto" (no macOS 15 em diante, clique direito > Abrir não contorna mais). Remova a marca uma vez, no Terminal:xattr -d com.apple.quarantine rk-darwin-arm64 chmod +x rk-darwin-arm64 ./rk-darwin-arm64 connect 192.168.0.10Alternativas sem quarentena: copiar com
scp/rsync, baixar comcurl -LO, ou compilar no próprio Mac commake build. Eliminar o aviso de vez exige assinar com Developer ID e notarizar (conta paga de desenvolvedor Apple). -
Windows: o SmartScreen pode avisar; escolha "Mais informações" > "Executar assim mesmo".
Arquivos de configuração
Ficam no diretório de configuração do usuário (~/.config/rk no Linux, ~/Library/Application Support/rk no macOS, %AppData%\rk no Windows):
| Arquivo | Lado | Conteúdo |
|---|---|---|
identity.pem |
ambos | chave Ed25519 e certificado desta máquina |
authorized.json |
alvo | teclados pareados |
known.json |
teclado | alvos pareados |
Apagar identity.pem gera uma identidade nova e obriga a parear de novo.