O nginx pode servir SSH e HTTP (S) ao mesmo tempo na mesma porta?

5

Contexto

Eu tenho um servidor pessoal que uso para a web. Às vezes preciso de SSH / SFTP para isso.

Disclamer: Eu tenho pouca experiência com nginx internals.

Problema

Esta manhã, eu descobri que o wifi gratuito em uma rede de cafés bem conhecidos estava bloqueando o SSH (na verdade, eles estão bloqueando qualquer coisa que não esteja no 80/443). Mas quando eu preciso de SSH, eu preciso disso, então eu procurei maneiras de compartilhar SSH e HTTPS na mesma porta.

O que eu olhei

Eu observei algumas soluções possíveis que podem ser executadas na porta 443:

  • SSHL : um multiplexador SSH / OpenVPN / HTTPS;
  • OpenVPN : uma solução VPN tem um multiplexador embutido para OpenVPN e HTTPS;
  • HAProxy : um servidor da Web / balanceador de carga também pode multiplexar tudo .

Tudo isso parece muito direto mas Eu realmente não gosto do fato de adicionar camadas e complexidade e possivelmente desacelerar as coisas apenas no caso improvável de Eu preciso do SSH no 443.

Colocando nginx no mix

Eu sei que nginx já suporta manipulação de streams TCP brutos. Então eu queria saber se eu poderia usar isso na porta 443 também diretamente em nginx . A ideia é que nginx poderia escolher usar o módulo http se ele reconhecesse HTTP (S) ou stream para todo o resto.

Perguntas

Nesse contexto, tenho duas perguntas:

  • O nginx é capaz de fazer tal distinção? (Não tenho certeza se conseguiria escutar na porta 443 nos blocos http e stream ao mesmo tempo.)
  • Em caso afirmativo, haveria algum problema de desempenho evidente com essa configuração? (Estou pensando na velocidade de transferência com o SFTP, por exemplo, não é realmente o SSH em si.)
por JohnW 08.10.2016 / 18:52

9 respostas

6

Desde que o nginx versão 1.15.2 adicionou a nova variável $ssl_preread_protocol . E no blog oficial adicionado post sobre como usar essa variável para multiplexar HTTPS e SSH na mesma porta link

Exemplo de configuração de SSH (por padrão) e HTTPS:

stream {
    upstream ssh {
        server 192.0.2.1:22;
    }

    upstream web {
        server 192.0.2.2:443;
    }

    map $ssl_preread_protocol $upstream {
        default ssh;
        "TLSv1.2" web;
    }

    # SSH and SSL on the same port
    server {
        listen 443;

        proxy_pass $upstream;
        ssl_preread on;
    }
}
    
por 26.07.2018 / 08:42
4

Ou, você poderia proxytunnel ssh através do seu nginx com conexão HTTP / S

Dê uma olhada: proxytunnel

    
por 09.10.2016 / 01:36
3

Eu tenho uma configuração de trabalho tunelamento ssh sobre tls na porta 443, usando o módulo de fluxo nginx. Eu também faço XMPP por TLS e HTTP normal na mesma porta. Eu faço o mutliplexing via ALPN.

(Você precisa do nginx > 1.13.10 para usar o módulo ssl_preread com o alpn link )

Minha configuração usa a versão docker do nginx, mas também deve funcionar sem o docker.

stream {
    # check ALPN for xmpp client or server and redirect to local ssl termination endpoints
    map $ssl_preread_alpn_protocols $ssl_multiplexer {
        "xmpp-client"     127.0.0.1:5422;
        "xmpp-server"     127.0.0.1:5469;
        "identifyssh"     127.0.0.1:8822;
        default           127.0.0.1:8443;
    }

    server {
        listen 443;
        ssl_preread on;
        proxy_pass $ssl_multiplexer;
        proxy_protocol on;
        set_real_ip_from  172.18.0.0/32;
    }

    # ssl termination for c2s connections
    server {
        listen 5422 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass ejabberd:5222;
    }

    # ssl termination for s2s connections
    server {
        listen 5469 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass ejabberd:5269;
    }

    # ssl termination for ssh connections
    server {
        listen 8822 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass yourserver:22;
    }
}

Se você quiser usar o material XMPP, adicione alguns registros SRV para apontar para a porta 443 de seus servidores, consulte o link

Se você deseja se conectar ao seu servidor ssh, é necessário agrupar sua sessão ssh em uma sessão ssl que envia a cadeia ALPN que você definiu em sua configuração de fluxo. Eu usei "identifshsh" no exemplo acima. Você pode usar qualquer coisa, mas tente não colidir com os nomes oficiais definidos: link

Para iniciar a sessão ssh do seu cliente para o servidor preparado, use:

ssh you@yourserver -o "ProxyCommand openssl s_client -alpn identifyssh -ign_eof -connect yourserver:443"

E você deve estar conectado.

Também devo observar que uso o proxy_protocol para manter os cabeçalhos dos clientes e o endereço IP ao passar para os meus back-ends.

Seu servidor http normal configurado na seção http {} deve cuidar disso:

server {
  listen 8443 ssl proxy_protocol;
  # ...
}

O melhor é que você não precisa de ferramentas como sslh, stunnel, proxytunnel ou outras para fazer isso funcionar. Você só precisa de um novo nginx e openssl. Espero que isso ajude alguém. Isso me ajudaria a cavar essas coisas.

    
por 04.06.2018 / 12:48
2

Esta questão está ligeiramente relacionada com outra que eu já respondi há pouco:

link

Sim, é tecnicamente possível diferenciar entre ssh e https tráfego e rotear a conexão adequadamente; no entanto, o nginx atualmente não tem esse suporte, que eu saiba.

No entanto, o que você pode fazer é simplesmente executar sshd diretamente na https port além da ssh one ( /usr/sbin/sshd -p 22 -p 443 ), e / ou usar o firewall e / ou bater de porta para diferenciar para onde as conexões para a porta 443 get são roteadas.

    
por 08.10.2016 / 22:41
2

Você pode configurar uma regra iptables para encaminhar as conexões do seu café bem conhecido na porta 443 para a porta 22. Alternativamente, devolva o tráfego de um retransmissor de porta em outro lugar na internet, alterando o número do pirt.

Apenas tentando resolver o problema com o nginx não vai funcionar.

    
por 08.10.2016 / 22:51
1

Até onde eu sei, atualmente o nginx não suporta isso.

Em SSH-2 , o cliente enviará uma mensagem de saudação para o servidor:

When the connection has been established, both sides MUST send an identification string. This identification string MUST be

 SSH-protoversion-softwareversion SP comments CR LF

No TLS 1.2 , os clientes precisam enviar primeiro:

  Client                                                Server

  ClientHello                   -------->
                                                   ServerHello
                                            [ChangeCipherSpec]
                                <--------             Finished
  [ChangeCipherSpec]
  Finished                      -------->
  Application Data              <------->     Application Data

Os clientes podem usar essas informações para implementação.

    
por 08.10.2016 / 20:07
1

Desde o Nginx Versão 1.9.0, NGINX suporta o módulo ngx_stream_core_module, ele deve ser ativado com o --with-stream. Quando o módulo de fluxo está habilitado, eles são possíveis para o proxy tcp do protocolo ssh

stream {
upstream ssh {
    server 192.168.1.12:22;
}
    server {
    listen        12345;
    proxy_pass    ssh;

} }

link

    
por 19.05.2017 / 19:03
0

Existe uma correção não-mantida para o nginx para suportar multiplexação de protocolo para SSH e HTTPS: link

No entanto, não é mais mantido, o projeto non-nginx que suporta o que você está procurando é: link

Eu sugiro que você use o SSLH em frente ao seu servidor nginx e ssh.

    
por 20.11.2017 / 11:14
0

Talvez você possa usar o nginScript para implementar seu próprio multiplexador? Veja aqui uma introdução: link

    
por 28.02.2018 / 18:57