Pythonのsshtunnelでポートフォワーディング

2021/11/04に公開

ポートフォワーディングを用いれば異なるネットワークにあるコンピュータと通信できます。
Pythonのsshtunnelパッケージでポートフォワーディングをしました。

環境

  • Raspberry pi3 x3
  • Python 3.8

構成

ローカルにRaspi0、SSHtunnelにRaspi1、センサーにRaspi2を用意します。Raspi0からRaspi1にSSHtunnelを構築し、ソケット通信でRaspi2からデータを取得します。local_bind_portは50000、sensor_portは12345にしています。

コード

import os
import time
from datetime import datetime, timezone
from influxdb import InfluxDBClient
from requests.api import get
import socket_client
from sshtunnel import SSHTunnelForwarder
import socket
import pickle
import numpy as np

# socket通信を組み立てる関数。引数はtunnel。
def create_client(tunnel0):
    client0 = socket_client.SocketClient("127.0.0.1", tunnel0.local_bind_port)
    client0.connect()
    return client0

# socket通信でデータを受信する関数。
def recv_data(client1):
    # サーバーからレスポンスを受ける。
    response = client1.send_rcv()
    data = pickle.loads(response)
    return data

SENSOR_IP = {'sensor_0': '192.168.xx.xx'}
SENSOR_PORT = {'sensor_0': 12345}

HUB_IP = "10.xx.xx.xx"
LOCALBIND_PORT = 12345

with SSHTunnelForwarder((HUB_IP, 22), 
ssh_host_key=None, 
ssh_username="pi", 
ssh_pkey="/home/pi/.ssh/public_key", 
remote_bind_address=(SENSOR_IP["sensor_0"], SENSOR_PORT["sensor_0"]), 
local_bind_address=("0.0.0.0", LOCALBIND_PORT)) as tunnel:
    client = create_client(tunnel)
    data = recv_data(client)
    print(data)

Discussion