Я помогаю с администрированием частной сети, и я хотел бы предоставить некоторые услуги (например, SSH с локальной переадресацией портов было бы здорово). К сожалению, мне, вероятно, не будет предоставлен доступ для установки переадресации портов в маршрутизаторе. Хотя я могу установить произвольное оборудование (любой компьютер, Raspberry Pi и т.д.). Чтобы обойти эту проблему, я подумал о реализации некоторой переадресации портов из закрытой сети в сеть, которой я управляю (например, переадресация порта 22 в мою сеть и оттуда доступ к "недоступной" сети через SSH и некоторая переадресация локальных портов, предоставить порт для VPN, все что угодно). Тем не менее, это кажется мне очень подверженным ошибкам, так как мне нужно было бы реализовать какое-то задание cron, чтобы проверить наличие исходящего соединения или установить его. Есть ли другие способы? Является ли то, что я представлял себе общим в любом случае? Спасибо за помощь.

РЕДАКТИРОВАТЬ

Сегодня я прочитал кое-что о маршрутизаторах с клиентскими VPN-возможностями - это будет работать? Я думал о реализации VPN где-нибудь, у меня есть полный контроль, а затем принудительно подключаю VPN-маршрутизатор клиента, и поэтому я получаю доступ к хостам, к которым я хотел бы подключиться удаленно.

1 ответ1

1

У меня было подобное требование пару лет назад. Я решил это с помощью следующего скрипта.

#!/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

Скрипт предназначен для запланированной работы cron (в моем случае, каждую минуту). Он проверяет наличие файла, указанного в переменной STARTFILE . Это было создано с помощью веб-интерфейса, но этот скрипт должен быть довольно легко модифицирован в соответствии с вашими потребностями. Причина контроля веб-интерфейса заключается в том, что клиент, возможно, не хочет иметь постоянный бэкдор в своей сети ... :) К сожалению, я не могу поделиться веб-частью, так как это часть гораздо более крупного проекта.

В любом случае, для того, чтобы это работало, вы должны настроить переменные REMOTE и KEYFILE чтобы они указывали на действительного пользователя / хоста и закрытый ключ. Остальное довольно необязательно. После этого просто создайте STARTFILE и запустите скрипт (или запланируйте его через cron), и туннель должен запуститься.

Предположим, что вы запускаете скрипт на сервере A , а для REMOTE задано значение user@B Если содержимое PORTFILE на A равно 9000 , вы должны иметь возможность войти на сервер A через B:9000 , используя любого действительного пользователя с сервера A

Я надеюсь, что все это имеет смысл ..

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .