sftpdav: Acesso Remoto via SSH com WebDAV

Recentemente, enfrentei um desafio ao tentar acessar arquivos de uma máquina que só permite conexão via SSH. Abrir portas adicionais ou instalar extensões de terceiros não eram opções viáveis por questões de segurança e compatibilidade, especialmente no macOS.

Foi assim que surgiu a ideia de criar o sftpdav, um programa que combina um cliente SFTP com um servidor WebDAV, permitindo acessar um diretório remoto via SSH e montá-lo localmente como se fosse um compartilhamento WebDAV.

Na prática, estou usando o rsync e mantendo os arquivos sincronizados entre a máquina local e o servidor remoto. O sftpdav é uma solução interessante, mas o desempenho não é tão bom. Ainda assim, foi muito proveitoso desenvolver essa solução e aprender mais sobre o protocolo WebDAV e SSH.

O código-fonte do sftpdav está disponível no GitHub: sftpdav.

Requisitos

A necessidade surgiu porque:

  • Ambiente Restrito: O servidor só permite conexão via SSH.
  • Segurança: Não posso expor outras portas no servidor.
  • Compatibilidade: O sshfs não tem suporte nativo no macOS, e não desejo instalar softwares adicionais.
  • Lock de Arquivos: O servidor WebDAV deve suportar bloqueio de arquivos (lock), necessário para meu caso de uso (o NFS também possui, mas não é tão simples de configurar).
  • user-space: A solução deve ser executada em user-space, sem necessidade de privilégios de administrador.

Com o sftpdav, é possível aproveitar a robustez do SSH e, ao mesmo tempo, oferecer a flexibilidade do WebDAV, que pode ser montado em sistemas Linux e macOS com comandos simples e em user-space.

Como Funciona o sftpdav

O programa realiza os seguintes passos:

  1. Leitura da Configuração SSH: Utiliza o arquivo ~/.ssh/config para obter informações como usuário, hostname, porta e arquivo de identidade.
  2. Conexão SFTP: Estabelece uma conexão SSH e, a partir dela, cria um cliente SFTP para acesso ao diretório remoto.
  3. Servidor WebDAV Local: Inicializa um servidor WebDAV com a biblioteca padrão do Go, expondo o diretório remoto via SFTP para ser montado localmente.
  4. Montagem do Compartilhamento: Com o servidor WebDAV em execução, o compartilhamento pode ser montado usando os comandos nativos do sistema.

Exemplos Práticos

Executando o sftpdav

Para iniciar o servidor WebDAV com acesso SFTP, execute:

./sftpdav -port 8811 -host sshserver

Parâmetros suportados:

  • -host: Nome do host conforme configurado no ~/.ssh/config.
  • -port: Porta local para o servidor WebDAV (padrão: 8811).
  • -remoteDir: Diretório remoto a ser exposto (padrão: ".").

Montando o Compartilhamento

No Linux

Use o comando mount com o tipo davfs:

sudo mount -t davfs http://localhost:8811 /mnt/sftp

No macOS

Use o comando mount_webdav:

sudo mount_webdav http://localhost:8811 /mnt/sftp

Para Desmontar

Em ambos os sistemas, para desmontar o compartilhamento, execute:

sudo umount /mnt/sftp

Limpando Arquivos de Dados Estendidos (macOS)

Como o WebDAV não suporta dados estendidos no macOS, podem ser criados arquivos iniciados por ._. Para removê-los, use:

dot_clean /caminho/do/diretorio

A Versão Original

A versão original era mais simples, consistindo em poucas linhas de código para criar um servidor WebDAV. No entanto, ela precisava ser executada no servidor remoto:

package main

import (
    "flag"
    "log"
    "net/http"
    "time"

    "golang.org/x/net/webdav"
)

func main() {
    localPortFlag := flag.String("port", "8811", "Local port for WebDAV server")
    dirFlag := flag.String("dir", "./", "Directory to share")
    flag.Parse()

    handler := &webdav.Handler{
        Prefix:     "/",
        FileSystem: webdav.Dir(*dirFlag),
        LockSystem: webdav.NewMemLS(),
    }

    s := &http.Server{
        Handler:        handler,
        Addr:           ":" + *localPortFlag,
        ReadTimeout:    15 * time.Second,
        WriteTimeout:   15 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    if err := s.ListenAndServe(); err != nil {
        log.Fatal(err)
    }
}

Então, criava-se um túnel SSH para acessar o servidor remoto e montar o compartilhamento WebDAV localmente.

Criando um Túnel SSH

ssh -L 8811:localhost:8811 sshserver

Neste exemplo, a porta 8811 da máquina local é redirecionada para a porta 8811 do servidor remoto, permitindo acesso local ao serviço WebDAV. Essa abordagem simples funcionava bem e é mais rápida que a versão atual.

Considerações Finais

O sftpdav é uma solução experimental, mas funcional. Apesar de apresentar alguma lentidão, cumpre o objetivo de fornecer acesso remoto via WebDAV usando apenas a porta SSH, mantendo a segurança e a simplicidade do ambiente.

A experiência com este projeto reforçou como é possível combinar diferentes protocolos para superar limitações e criar soluções interessantes e seguras.

Caso tenha dúvidas ou sugestões, fique à vontade para entrar em contato ou abrir uma issue.

Cesar Gimenes

Última modificação