Как сделать туннелирование python SSH с 2FA?

Я пытаюсь написать скрипт Python, который подключается к базе данных, но эта база данных доступна только в том случае, если вы сначала подключитесь по SSH к хосту-бастиону. Вот что мне нужно сделать из командной строки для настройки туннеля:

$ ssh -i /path/to/my/key/file.pem -A -L 3307:mydb1.fsd23rqr.us-east-1.rds.amazonaws.com:3306 [email protected]
[ec2-user@ip-X-X-X-X ~]$ 

Я создал скрипт Python, используя эту библиотеку sshtunnel, чтобы сделать то же самое. вещь. Оно работает:

#!/usr/bin/env python
from sshtunnel import SSHTunnelForwarder
import MySQLdb as db
import pandas as pd

print('\nAbout to try connecting')
with SSHTunnelForwarder(
    ('my-ssh-host.without.2fa', 22),
    ssh_username='my_ssh_username1',
    ssh_pkey='/path/to/my/key/file.pem',
    remote_bind_address=('mydb1.fsd23rqr.us-east-1.rds.amazonaws.com', 3306),
    local_bind_address=('0.0.0.0', 3307)
) as tunnel:
    print "Connection Established"
    print pd.read_sql_query(
        "select 'Hello' from dual",
        db.connect(
            host='127.0.0.1',
            port=tunnel.local_bind_port,
            user='my_db_username1',
            passwd='****************',
            db='my_db_instance_1'
        )
    )

Производит:

About to try connecting
Connection Established
   Hello
0  Hello

Но теперь мне нужно использовать другую комбинацию БД и бастиона. Этот бастион имеет настройку двухфакторной аутентификации (2FA), поэтому, когда я подключаюсь к нему по ssh, он спрашивает меня, какой метод 2FA я выбираю. Если я выбираю метод № 1, он отправляет push-уведомление на мой телефон Android, которое я должен одобрить:

$ ssh -i /path/to/my/key/rsa -A -L 3307:mydb2.fsd23rqr.us-east-1.rds.amazonaws.com:3306 [email protected]
Duo two-factor login for my_ssh_username2

Enter a passcode or select one of the following options:

 1. Duo Push to XXX-XXX-9671
 2. Phone call to XXX-XXX-9671
 3. SMS passcodes to XXX-XXX-9671 (next code starts with: 1)


Passcode or option (1-3): 1

<WAIT FOR ME TO CLICK APPROVE ON MY ANDROID>

Success. Logging you in...
[my_ssh_username2@ip-X-X-X-1X ~]$

Но когда я пытаюсь настроить туннель с помощью sshtunnel точно так же, как для бастиона с поддержкой 2FA, происходит сбой:

About to try connecting
Connection Established
Enter DB password:
2018-08-29 15:31:43,985| ERROR   | Could not establish connection from ('127.0.0.1', 3307) to remote side of the tunnel
Traceback (most recent call last):
  <stack-trace snipped>
  File "python2.7/site-packages/MySQLdb/__init__.py", line 81, in Connect
    return Connection(*args, **kwargs)
  File "python2.7/site-packages/MySQLdb/connections.py", line 193, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
_mysql_exceptions.OperationalError: (2013, "Lost connection to MySQL server at 'reading initial communication packet', system error: 0")

Как я могу написать скрипт Python для подключения к базе данных Mysql через SSH-туннель, если sshing для этого хоста требует 2FA ??


person Saqib Ali    schedule 29.08.2018    source источник
comment
Никакой помощи на python, но для стороны ssh вы можете установить туннель через закрытый ключ, только если вы не создаете оболочку на другом конце? Возможно, вы захотите поэкспериментировать с параметрами -f и -N для ssh, чтобы выяснить это, и если да, посмотрите на повторную реализацию этой функциональности.   -  person ivanivan    schedule 31.08.2018


Ответы (1)


Вам необходимо настроить интерактивный сеанс SSH, чтобы ввести параметры, предоставляемые сервером с поддержкой 2fa. Кратко взглянем на код библиотеки sshtunnel. Похоже, что для подключения к шлюз, а также настроить туннель. Методы, реализующие оба из них, не имеют опции для предоставления интерактивного tty для пользовательского ввода.

Например, метод, выполняющий шлюзовое соединение, говорит следующее:

def _connect_to_gateway(self):
    Open connection to SSH gateway
     - First try with all keys loaded from an SSH agent (if allowed)
     - Then with those passed directly or read from ~/.ssh/config
     - As last resort, try with a provided password

Как видите, здесь нет возможности выполнять интерактивные команды сеанса ssh.

Таким образом, вы можете либо расширить код с помощью paramiko для настройки интерактивного сеанса, либо написать свой собственный код с помощью paramiko для управления подключением к шлюзу и настройкой туннеля. Например, paramiko предоставьте этот пример для выполнения интерактивных сеансов.

person moebius    schedule 04.09.2018