Pythonコードを使用してインターネットを介してLANを起動する方法は?

Pythonコードを使用してインターネットを介してLANを起動する方法は?

私のホームネットワーク図は、次のように非常に簡単です。

internet       --> Optical modem --> router      --> pc1 ,pc2
111.111.111.111--> 192.168.1.1   -->192.168.31.1 --> 192.168.31.144,192.168.31.173

ISPは、111.111.111.111光モデムのIPアドレス192.168.1.1、ルーターのIPアドレス192.168.31.1、PC1のIPアドレス192.168.31.144、PC2のIPアドレス192.168.31.173、PC1のMACアドレスを想定していますxx.xx.xx.xx

私のルーターで動作openwrtし、ルーターにポート転送ルールを追加し、ファイアウォールの電源を入れます。

forwarding rule
name        protocl       outer port    inner IP address   inner port 
wakeonwan   UDP           9             192.168.31.144      9
ssh         TCP and UDP   10000         192.168.31.1        22

そしてopenwrtでIPアドレスとMacをバインドします。

ip address               mac               interface
192.168.31.144           xx.xx.xx.xx       ??

次のオプションからどのインターフェイスを選択する必要がありますか?

ここに画像の説明を入力してください。

私のルーターにTelnetを接続します。

ssh [email protected] -p 10000

ルータで wol コマンドを実行します。

/usr/bin/wol -i 192.168.31.255 xx.xx.xx.xx

pc1はルータから目覚めることができます!
次のPythonコードを使用してpc1を終了し、pc2から目覚めますwakeonlan.py

from wakeonlan import send_magic_packet
send_magic_packet('xx.xx.xx.xx')

pc2でこのコマンドを実行すると、python3 wakeonlan.pypc1を正常に起動できます。

リモートでコマンドを実行してもpython3 wakeonwan.py(たとえば、会社のコンピュータで)私のpc1を起動できません。

cat wakeonwan.py
mac = "xx.xx.xx.xx"
target_ip = "111.111.111.111"
from wakeonlan import send_magic_packet
send_magic_packet(mac, ip_address=target_ip,port=9)

エラーは発生しません。 pc1が目覚めない理由は何ですかwakeonwan.py
libでやってみよう-- paramiko

pip install paramiko

アイテwakeonwan-paramiko.py

import paramiko
from contextlib import contextmanager
host = '111.111.111.111'
username = 'root'
password = 'password'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(host, username=username, password=password,port=10000)
stdin, stdout, stderr = ssh.exec_command("/usr/bin/wol -i 192.168.31.255 xx:xx:xx:xx")
ssh.close()

python3 wakeonwan-paramiko.py外部ネットワークから自分の家のコンピュータを目覚めさせることはできますか?wakeonwan.pyリモートウェイクアップコンピュータをプログラムする方が簡単ですか?
どうすれば修正できますか?

答え1

ローカルネットワークの外側からWake-on-LANパケットを送信するときのトリッキーな部分は、完全にパッシブPC1がパケットを受信できるように、ルータにパケットをローカルネットワークに送信させることです。

マジックパケットはルーターの外部IPアドレスに送信されますユニキャストパケット。ルータの転送ルールは、ターゲットPCの独自のIPアドレスを内部IPアドレスとして指定します。したがって、ユニキャストトラフィックを転送するための標準的な手順では、ルーターは最初にターゲットPCのMACアドレスを見つけるためにARP要求を送信しますが、ターゲットPCがダウンしているため応答はありません。 Wake-on-LANパケットを待つネットワークインタフェースは、低電力受信専用モードです。通常、ARP要求に応答できません。

ARP 要求が失敗した場合、ルータは「Host Unreachable」を示す ICMP エラー パケットを再送信できます。ただし、Pythonwakeonlanモジュールには、ICMPメッセージが受信されていないと仮定しても、これらのエラー応答を処理する能力はないようです。妄想への道はファイアウォールによってろ過されました。

実際、MACアドレスをマジックパケットペイロードに含めることは、ルータがそれについて知っても興味もないため、あまり役に立ちません。ルータにとって、マジックパケットは別のTCPまたはUDPパケットに過ぎず、正常に処理されます。

マジックパケットがブロードキャストになるには、内部ネットワークのブロードキャストアドレスに送信するように転送ルールを設定する必要があります。これにより、ルータはパケットを内部ネットワークに転送する前にARPクエリを実行する必要がなくなります。したがって、内部ネットワークのネットマスクが255.255.255.0の場合、転送ルールでは内部IPアドレスとして192.168.31.255を使用する必要があります。

しかし...@ABがコメントで述べたように、Linuxベースのルーターは通常ユニキャストをブロードキャストに変換するのが好きではないので、このアプローチはうまくいかないかもしれません。

別の解決策は、ターゲットPCの静的ARPテーブルエントリをルータのARPテーブルに追加して、ARPルックアップを必要とせずにパケットが内部ネットワークに転送されるようにすることです。

迅速なソースコード検査で、ネットワークPythonモジュールの目覚めSOCK_DGRAMを使用しているようです。これはUDPを使用することを意味します。したがって、転送ルールを「TCPとUDP」から「UDPのみ」に変更できる必要があります。

関連情報