Porta do túnel (serviço) fora da rede inacessível externamente

0

Estou ajudando com a administração de uma rede privada e gostaria de expor alguns serviços (por exemplo, o SSH com o encaminhamento de porta local seria ótimo). Infelizmente, eu provavelmente não será concedido acesso para instalar qualquer encaminhamento de porta no roteador. O que eu posso fazer é instalar hardware arbitrário (qualquer tipo de computador, Raspberry Pi, etc.). Para contornar este problema, pensei em implementar algum tipo de encaminhamento de porta da rede fechada para a rede que eu controle (como redirecionar a porta 22 para minha rede e acessar a rede "inacessível" via SSH e fazer um encaminhamento de porta local) fornecer uma porta para VPN, qualquer coisa). No entanto, isso parece muito propenso a erros, já que eu precisaria implementar algum cron job para verificar se há uma conexão de saída ou se é necessário estabelecer uma conexão. Existem outras maneiras? É o que eu imaginei comum em qualquer caso? Obrigado pela sua ajuda.

EDITAR

Hoje li algo sobre roteadores com recursos VPN de cliente - isso funcionaria? Eu pensei em implementar uma VPN em algum lugar que eu tenho controle total e, em seguida, forçar o roteador VPN cliente para se conectar e assim me dar acesso aos hosts que eu gostaria de alcançar remotamente.

    
por bash.d 21.05.2017 / 16:54

1 resposta

1

Eu tive uma exigência semelhante há alguns anos. Eu resolvi com o seguinte script.

#!/bin/bash

# This script is designed to be scheduled by cron as often as is required
# If STARTFILE exists, it will start/restart the connection
# If STOPFILE exists, it will stop the connection
# If PORTFILE exist, makes sure the tunnel is started, to survive restarts
#
# PORTFILE will always contain the port number on the remote host that the SSH connection is tunneled to
#
# This utilizes the control socket option of SSH to control the tunnel

# Base name, used by other variables
NAME="ssh_tunnel"

# Create this file to start the server
STARTFILE="/etc/$NAME/$NAME.start"

# This file will contain the port number on the remote server to connect to to access the tunnel
PORTFILE="/etc/$NAME/$NAME.port"

# Create this file to stop the server
STOPFILE="/etc/$NAME/$NAME.stop"

# The user and host to connect the tunnel to
REMOTE="user@hostname"

# The private key of the user on the remote server to create the tunnel to
KEYFILE="/etc/$NAME/.ssh/$NAME"

# The control socket of the SSH connection
SOCKET="/var/run/$NAME.socket"

# First port to try and listen on at remote host
LISTEN=9000

# Last port to try and listen on at remote host
MAXPORT=9999

SSH=$(which ssh)

# We need to run as root, otherwise it will fail
if [ "$(id -u)" != "0" ]; then
    echo "Must be run as root!"
    exit 1
fi

# Make directory if if doesn't exist
if [ ! -d "/etc/$NAME" ]; then
    mkdir "/etc/$NAME"
fi

# Starts the tunnel and updates the control files
start_tunnel() {
    # Remove port file, since it is outdated, if it exists
    if [ -f ${PORTFILE} ]; then
        rm -f ${PORTFILE}
    fi

    # Start tunnel and wait 2 seconds.. It the tunnel isn't up, then the port is busy (or the public key is foobar)
    while true; do
        ${SSH} -M -S ${SOCKET} -2 -4 -C -f -N -i ${KEYFILE} -o CheckHostIP=no -o KeepAlive=yes -o StrictHostKeyChecking=no -o ExitOnForwardFailure=yes -o BatchMode=yes ${REMOTE} -R $LISTEN:localhost:22
        sleep 2
        check_tunnel && break
        set LISTEN=LISTEN+1
        if [ $LISTEN -eq $MAXPORT ]; then
            # No ports available (or more likely, the public key is incorrect)
            exit 1
        fi
    done
    echo ${LISTEN} > ${PORTFILE}

    # Remove startfile, since the process is now started
    if [ -f ${STARTFILE} ]; then
        rm -f ${STARTFILE}
    fi

}

# Stops the tunnel and cleans up the control files
stop_tunnel() {
    # Remove portfile and stopfile if they exist
    if [ -f ${PORTFILE} ]; then
        rm -f ${PORTFILE}
    fi
    if [ -f ${STOPFILE} ]; then
        rm -f ${STOPFILE}
    fi
    ${SSH} -S ${SOCKET} -O exit ${REMOTE} > /dev/null 2>&1
}

# Check if the tunnel is up
check_tunnel() {
    if [ -e ${SOCKET} ]; then
        (${SSH} -S ${SOCKET} -O check ${REMOTE} 2>&1 | grep -q "running") && return 0
    fi
    return 1
}

# Use a lock file so only one instance is running
(
    flock -n 9 || exit 1

    if [ -f ${STARTFILE} ]; then
        # Restart if running, otherwise just start
        check_tunnel && stop_tunnel
        start_tunnel
    elif [ -f ${STOPFILE} ]; then
        # Stop if running
        check_tunnel && stop_tunnel
    elif [ -f ${PORTFILE} ]; then
        # The tunnel should be running, might not be after a reboot, for example
        check_tunnel || start_tunnel
    fi

) 9>/var/run/$NAME.lock

O script foi projetado para ser agendado como uma tarefa cron (no meu caso, a cada minuto). Verifique a existência do arquivo especificado na variável STARTFILE . Isso foi criado por meio de uma interface da Web, mas deve ser muito fácil modificar esse script para atender às suas necessidades. A razão para o controle da interface web é que o cliente talvez não queira ter um backdoor permanente em sua rede .. :) Infelizmente, não posso compartilhar a web part, pois isso faz parte de um projeto muito maior.

De qualquer forma, o que você deve configurar para que isso funcione é configurar as variáveis REMOTE e KEYFILE para que ele aponte para um usuário / host e uma chave privada válidos. O resto é bem opcional. Depois disso, basta criar o STARTFILE e executar o script (ou agendá-lo via cron) e o túnel deve ser iniciado.

Digamos que você esteja executando o script no servidor A e REMOTE esteja definido como user@B . Se o conteúdo de PORTFILE on A for 9000 , você poderá fazer o login no servidor A via B:9000 , usando qualquer usuário válido do servidor A .

Espero que tudo isso faça sentido ...

    
por 23.05.2017 / 09:28