Схема того, что я пытаюсь выполнить:SSH сервер направляет туннель пользователем
$ sftp [email protected]
SSHCLIENT_JOE --------> GATEWAY_SERVER (does logic by username to determine
| socket to forward the connection to.)
|
\ 127.0.0.1:1030 CONTAINRR_SSHD_SALLY
---> 127.0.0.1:1031 CONTAINER_SSHD_JOE
127.0.0.1:1032 CONTAINER_SSHD_MRAYMOND
Это кажется ближе всего к тому, что я пытаюсь сделать: paramiko server mode port forwarding http://bitprophet.org/blog/2012/11/05/gateway-solutions/
Но вместо клиент, выполняющий ProxyCommand или запрашивающий канал «direct-tcpip», я хочу, чтобы пересылка выполнялась сервером, незаметно для клиента. Я пытаюсь сделать это с помощью сервера paramiko, беря объект транспорта подключаемого клиента и создавая канал прямой tcpip от имени клиента, но я сталкиваюсь с блокпостами. Я Использование https://github.com/paramiko/paramiko/blob/master/demos/demo_server.py в качестве шаблона
# There's a ServerInterface class definition that overrides check_channel_request
# (allowing for direct-tcpip and session), and the other expected overides like
# check_auth_password, etc that I'm leaving out for brevity.
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 2200))
except Exception as e:
print('*** Bind failed: ' + str(e))
traceback.print_exc()
sys.exit(1)
try:
sock.listen(100)
print('Listening for connection ...')
client, addr = sock.accept()
except Exception as e:
print('*** Listen/accept failed: ' + str(e))
traceback.print_exc()
sys.exit(1)
print('Got a connection!')
try:
t = paramiko.Transport(client)
t.add_server_key(host_key)
server = Server()
try:
t.start_server(server=server)
except paramiko.SSHException:
print('*** SSH negotiation failed.')
sys.exit(1)
# Waiting for authentication.. returns an unwanted channel object since
# it isn't the right "kind" of channel
unwanted_chan = t.accept(20)
dest_addr = ("127.0.0.1", 1030) # target container port
local_addr = ("127.0.0.1", 1234) # Arbitrary port on gateway server
# Trying to put words in the client's mouth here.. fails
# What should I do?
print(" Attempting creation of direct-tcpip channel on client Transport")
tunnel_chan = t.open_channel("direct-tcpip", dest_addr, local_addr)
print("tunnel_chan created.")
tunnel_client = SSHClient()
tunnel_client.load_host_keys(host_key)
print("attempting connection using tunnel_chan")
tunnel_client.connect("127.0.0.1", port=1234, sock=tunnel_channel)
stdin, stdout, stderr = tunnel_client.exec_command('hostname')
print(stdout.readlines())
except Exception as e:
print('*** Caught exception: ' + str(e.__class__) + ': ' + str(e))
traceback.print_exc()
try:
t.close()
except:
pass
sys.exit(1)
выходного тока:
Read key: bc1112352a682284d04f559b5977fb00
Listening for connection ...
Got a connection!
Auth attempt with key: 5605063f1d81253cddadc77b2a7b0273
Attempting creation of direct-tcpip channel on client Transport
*** Caught exception: <class 'paramiko.ssh_exception.ChannelException'>: (1, 'Administratively prohibited')
Traceback (most recent call last):
File "./para_server.py", line 139, in <module>
tunnel_chan = t.open_channel("direct-tcpip", dest_addr, local_addr)
File "/usr/lib/python2.6/site-packages/paramiko/transport.py", line 740, in open_channel
raise e
ChannelException: (1, 'Administratively prohibited')
В настоящее время у нас есть прямой вперед сервер SFTP, где клиенты подключаются и они CHROOT-й изд к их соответствующему фтпу каталогам. Мы хотим переместить клиентов в контейнеры lxc, но не хотим изменять, как они подключаются к sftp .. (Так как они, вероятно, используют клиентов gui ftp, например filezilla.) Я также не хочу создавать интерфейс моста и назначьте новые ips всем контейнерам. Таким образом, контейнеры не имеют отдельных ips от хоста, они имеют одинаковое сетевое пространство. Клиентские контейнеры sshds будут связываться с отдельными портами на localhost. Таким образом, у них могут быть уникальные порты, и логика выбора порта может быть концептуально перенесена на ... простой сервер на физическом хосте.
Это скорее доказательство концепции, и общее любопытство с моей стороны. SSH сервер
Я не знаю paramico, но, как правило, SSH необходимо «где-то», и если ваш шлюз не является устройством, которое ведет переговоры о соединении (т. Е. Вы не хотите использовать ProxyCommand) Я ожидаю, что вам нужно будет использовать NAT для подключения TCP-соединения к другому хосту. – ghoti
@ghoti Так что подключение двух каналов не является возможным. Я не могу пройти через 2 sshd, если исходный клиент явно не запрашивает ProxyCommand? Кажется, это стена, на которую я нажимаю. Я хотел бы автоматизировать NAT-порты портов, хотя я могу только сделать логику, когда я получу имя пользователя клиента. Из того, что я могу сказать, это получается только после согласования соединения с sshd. Так что это сценарий с курицей и яйцом. – mraymond
Хорошо, не могу сделать это в комментариях, я дал ответ ниже. – ghoti