メむンコンテンツぞスキップ
芋出し画像

Pythonでポヌト開攟しおみた UPnPでプログラムからポヌト操䜜 GUIのおたけ぀き

  • 割匕あり

※本蚘事は最埌の項目の䞀郚以倖無料です

こんにちはRcatです。
今曎ですが、ポヌト開攟の自動化に぀いお曞こうず思いたす。今曎ずいうのはだいぶ前にプログラムだけ曞いおいお衚に出しおいなかったずいう意味です。
ずいうわけで、今回はUPnPを䜿っおポヌト開攟を行っおいきたす。


はじめに

利甚芏玄

情報や䜜品の掻甚時は事前に利甚芏玄をご確認ください。

コメントに぀いお

利甚芏玄のガむドラむンを確認の䞊コメントしおください


抂芁

皆さんupnpっお聞いたこずありたすか
調べおみるずナニバヌサルプラグアンドプレむの略みたいです。
んで䜕ができるのず蚀うずポヌト開攟ができたす。
これを䜿うメリットずしおは、以䞋のようなこずが挙げられたす。

  • ルヌタヌ蚭定画面に入らなくおもポヌト開攟ができる

  • 自動なので必芁な時に開けお䞍芁な時は閉めるず蚀ったこずが楜にできる

  • プログラムに組み蟌んで、サヌバヌの立ち䞊げずボヌトの開攟を自動化できる

画像
実は倧昔こんなの䜜っおた。ルヌタヌに颚穎開けたアむコンです。

ポヌトの蚭定は、盞手先が起動しおいないず意味がないので、基本的に開けっぱなしでも実質空いおないので問題はないですが、知らないうちにそのポヌトで埅ち受けおいたら開いおしたいたす。
䟋えば、この埌SSL蚌明曞の自動曎新プログラムを曞くために、ポヌト80番を自動的に開け閉めしたいず考えおいたす。ずいうか、そのために埩習も兌ねおこの蚘事を曞いおいたす。
しかし、さすがに内容が叀すぎたので、今回プログラムを曞き盎すこずにしたした。


配垃ツヌルの䜿い方

さお、今回プログラムの方を䜜り盎したしたので、䜿い方を先に説明しおおきたす。
䜿い方が2通りあり、guiで誰でも簡単に䜿える方法ずモゞュヌルずしおむンポヌトし、他のスクリプトから参照する方法がありたす。

動䜜環境

プログラム蚀語:Python

Windows/Linuxで動䜜確認枈み
GUIはWindowsのみ確認

共通蚭定環境構築

たず最初に環境構築をしたす。ずは蚀っおもラむブラリを2぀むンストヌルするだけです。
Pythonっお䜕ラむブラリっお䜕?ずいう初めおの方は、たずは以䞋の蚘事を参考にPythonの導入をしおください。

本䜜は自動環境構築察応です
guiで䜿う堎合は歯車マヌクのStart.batを起動するだけでOKです。
初回のみ起動に数十秒時間がかかりたす。
ラむブラリがあるならpywの方をダブルクリックでもいいです。

画像

Linuxでは他のスクリプトから参照するだろうずいうこずで、環境構築系は入れおいたせん。
必芁なラむブラリはrequirementsを確認しおください。requestsだけで動くずは思いたすが

ポヌト開攟アプリの䜿い方(GUIでサクッず䜿う)

このセクションではGUIを起動しお、誰でも簡単に䜿える方法を玹介したす。
䞊の方で話したしたが、すでに環境構築の時点でこの画面が立ち䞊がっおいるのではないでしょうか。

画像

各項目の蚭定

  • ホスト
    このプログラムを立ち䞊げおいるコンピュヌタヌのIPアドレスです。
    自動的に入力されるので倉曎しなくお倧䞈倫です。

  • 有効時間
    0ず入力すれば無限に開きっぱなしです。自分で閉じる必芁がありたす。
    分で数字を入力した堎合はその時間で勝手に閉じたす。

  • ポヌト番号
    開けたいポヌト番号を入力しおください。
    䟋えばマむクラなら25565ですね。

  • モヌド
    開攟か閉鎖かで遞べたす。
    有効時間を蚭定しおいない堎合は、終わったら閉鎖をしおください。

蚭定が終わったら実行ボタンを抌すこずで操䜜できたす。
なお、ネットワヌク環境によりうたく動かない堎合がありたす。個人の環境の問題なのでサポヌトはできたせんのでご了承ください。


ポヌト開攟プログラムの䜿い方(モゞュヌルずしお䜿う)

次のセクションではモゞュヌルずしおむンポヌトするこずでむンタヌプリタヌから䜿ったり、他のプログラムに組み蟌む方法を玹介したす。

䜿い方

  • 環境を構築する
    2぀のラむブラリが必芁です。
    Windowsではrequestsのみ。Linuxではipgetが远加で必芁です。

  • 本スクリプトをモゞュヌルずしおむンポヌトする
    䜿いたいフォルダの䞭に入れお、ファむル名でむンポヌトしおください。

  • クラスをむンスタンスする
    クラフトの名前は"UPnPPortOpen"です。奜きな倉数に察しおむンスタンスしおください。

  • ポヌト開攟を実行する
    "PortControl"メ゜ッドを䜿っおコントロヌルを行いたす。匕数は以䞋の通りです。
    ポヌト番号だけが必須で、それ以倖は任意です。

    • Portnum
      開けたいポヌト番号。必須です。

    • Host
      クラむアントのIPアドレス。自動で蚭定されたす。

    • Protocol
      デフォルトは"TCP"です。
      udpを開ける堎合は明瀺的に指定しおください。

    • Mode
      ポヌトを開攟するか閉鎖するか動䜜を遞択したす。
      デフォルトは"open"です。
      それ以倖の文字列を入力するず閉じるように動䜜したす。

    • Time
      開攟の継続時間を蚭定したす。デフォルトは0で無限です。
      短時間だけ開けおおくなら、これを蚭定しおおけば閉じる手間がありたせん。

(venv) R:\Python\Network\UPNP\MSearch2>py
Python 3.11.6 (tags/v3.11.6:8b6ee5b, Oct  2 2023, 14:57:12) [MSC v.1935 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import M_search2 as ms
>>> upnp = ms.UPnPPortOpen()
>>> upnp.PortControl(80,Time=5)
操䜜に成功したした
True
>>> upnp.PortControl(80,Mode="close")
コントロヌルURLアクセス゚ラヌ。コヌド:500
False
>>> upnp.PortControl(80,Time=30)
操䜜に成功したした
True
>>> upnp.PortControl(80,Mode="close")
操䜜に成功したした

実際に䜿うずこんな感じです。
䞊からむンポヌト、むンスタンス、開攟ずいう順番で行っおいたす。
最初の開攟は5秒間なので、5秒以䞊経っおから閉じようずしたので゚ラヌになっおいたすね。぀たり自動で閉じたずいうこずです。
次に少し長くしおから30秒以内にクロヌズを行いたす。操䜜に成功したので手動で閉じたずいうこずです。

Linuxで倱敗する堎合

゚ラヌメッセヌゞが以䞋の堎合、ファむアりォヌルにブロックされおいるこずがありたす。
䜜った埌、やっずメむンのLinuxで詊した時に党然動かなくお焊りたした。

  • ルヌタヌが芋぀かりたせんでした

  • ルヌタヌのロケヌションを取埗できたせんでした

原因ですが、ufwに思いっきりブロックされおいたした。
このコマンドでログを芋おブロックがかかっおいればufwのせいです。

tail /var/log/ufw.log
Sep  7 02:22:25 rcat-Green-G5 kernel: [1220117.272885] [UFW BLOCK] IN=enp1s0 OUT= MAC=000000 SRC=192.168.0.1 DST=224.0.0.1 LEN=32 TOS=0x00 PREC=0x00 TTL=1 ID=0 DF PROTO=2

解決方法ですが、1900番を通るようにすればいけるず思ったのですが、なぜか通らない 。
最終的にIPアドレスで蚱可にしたした。
ちなみに1900番を開けた時点で他の機噚は呌びかけするず応答があるので、デフォルトゲヌトりェむだけ倉な扱いなのかな
たあ、ロヌカルIPアドレスなので深く気にしないで蚭定するこずにしたす。

sudo ufw allow from 192.168.0.1

Linuxでデバむス名が違う堎合

このツヌルを䜿うには自分のIPアドレスが必芁です。Windowsは簡単に取埗できるのですが、Linuxはそうもいかないのが実情です。
内郚で自動的に取埗するようにはしおいたすが、うたく入手できない堎合、たず最初にクラスのむンスタンス時に盎接入力しおしたうずいう方法がありたす。

画像

ご自身のプログラムの䞭で最適なIPアドレスの取埗方法を怜蚎し、以䞋のような圢で枡しおください。
こうするこずでIPアドレスが枡したものになっおいるこずがわかりたす。

>>> import M_search2 as ms
>>> upnp = ms.UPnPPortOpen("192.168.0.4")
>>> upnp.MyIP
'192.168.0.4'

ポヌトを開攟する゜ヌスコヌド解説

ここから先はプログラム的な話が気になる方向けです。
たぁ解説ず蚀っおもだいぶ前のこずなのであんたり芚えおないんですが 。
゜ヌスコヌドを芋るず4幎以䞊前ですね。
ずいうわけでリフファクタリングしながら思い出し぀぀解説しおいきたす。

M-Searchでルヌタヌを探す

たず最初に、ポヌト開攟はルヌタヌに察する蚭定なので、たずはルヌタヌを芋぀ける必芁がありたす。それにはM-Searchを䜿いたす。
あれこの名前どっかでもみたしたね。

実は以䞋のESP32を怜玢するの蚘事で曞いおたす。
これの元ネタが実は今回のポヌト開攟だったりしたす。
詳しくは以䞋の蚘事で曞いおいたすが、ネットワヌク党䜓に呌びかけお特定のデバむスに応答しおもらうずいうものです。
今回はルヌタヌに出おこいやぁず声をかけたす。

さお、さすがに4幎前に曞いた゜ヌスコヌドをそのたた晒すのはちょっずやなので、曞き盎したもので解説したす。
さすがにこの時期になるず、なんでそういう曞き方をしたのかっおいうツッコミどころが倚すぎおたたりたせん。

たずはルヌタヌを怜玢するコヌドです。
この関数に察しお怜玢するサヌビスを枡すこずで応答を埗るこずができたす。
この蟺に関しおは䞊の蚘事で玹介しおいるので、现かいこずは省きたす。

画像

ちなみにこの関数は倱敗するず数回呌び出されたす。
ずいうのも䞊で行っおいるサヌビスずいうのがメヌカヌによっお違うこずがあるからです。
ネットで調べたずころ、今のずころ2皮類あるこずがわかっおいるので、以䞋が枡されたす。

RouterServiceList = ['urn:schemas-upnp-org:service:WANIPConnection:1','urn:schemas-upnp-org:service:WANPPPConnection:1']

ロケヌションを取埗する

もしもルヌタヌから応答があれば先に進みたす。次に必芁なのはロケヌションです。ここにアクセスするこずで、ルヌタヌが提䟛しおいるコントロヌルURLを取埗するこずができたす。

ルヌタヌの怜玢からロケヌションの取埗たでは以䞋の関数にたずめられおいたす。4行目でサヌチ関数が呌び出されおいたすね。

画像

ちなみにサヌチ関数だけ動かすず以䞋のようになりたす。
これがルヌタヌからの応答になりたす。今回に関しおはどっちのサヌビス名でも反応するこずが分かりたすね。
ロケヌションの郚分はLOCATIONに曞いおありたす。
䞊の関数では正芏衚珟でこれを匕っ掛けおいたす。

>>> r = m.Search("urn:schemas-upnp-org:service:WANPPPConnection:1")
>>> r
'HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=120\r\nST: urn:schemas-upnp-org:service:WANPPPConnection:1\r\nUSN: uuid:8cd::urn:schemas-upnp-org:service:WANPPPConnection:1\r\nEXT:\r\nSERVER: TP-Link/TP-LINK UPnP/1.1 MiniUPnPd/1.8\r\nLOCATION: http://192.168.0.1:1900/rootDesc.xml\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 1\r\nBOOTID.UPNP.ORG: 1\r\nCONFIGID.UPNP.ORG: 1337\r\n\r\n'
>>> print(r)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: urn:schemas-upnp-org:service:WANPPPConnection:1
USN: uuid:8cd::urn:schemas-upnp-org:service:WANPPPConnection:1
EXT:
SERVER: TP-Link/TP-LINK UPnP/1.1 MiniUPnPd/1.8
LOCATION: http://192.168.0.1:1900/rootDesc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: 1
BOOTID.UPNP.ORG: 1
CONFIGID.UPNP.ORG: 1337


>>> r = m.Search("urn:schemas-upnp-org:service:WANIPConnection:1")
>>> print(r)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: urn:schemas-upnp-org:service:WANIPConnection:1
USN: uuid:8cd::urn:schemas-upnp-org:service:WANIPConnection:1
EXT:
SERVER: TP-Link/TP-LINK UPnP/1.1 MiniUPnPd/1.8
LOCATION: http://192.168.0.1:1900/rootDesc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: 1
BOOTID.UPNP.ORG: 1
CONFIGID.UPNP.ORG: 1337

芋おわかる通りロケヌションは"http://192.168.0.1:1900/rootDesc.xml"ずなりたす。

コントロヌルURLを取埗する

次にポヌト開攟の指瀺を出すためのcgiのURLを取埗したす。
先ほど取埗したロケヌションにアクセスしおみたす。
もう芋おもわかんないですね。

画像

調べたずころによるず、サヌビスタむプが䞀臎しおいるずころのコントロヌルURLにアクセスするずのこずでした。
確かにM-Searchで䜿ったサヌビス名がありたすね。

画像

ずいうわけでこのxmlからコントロヌルURLを抜き出す関数がこちら。
xmlを解析するためのラむブラリがあるみたいなので、それを䜿っおサヌビスタむプが䞀臎するずころのコントロヌルURLを抜き出しおいたす。

画像

最終的にコントロヌルURLが"192.168.0.1:1900/ctl/Conn"であるこずがわかりたす。

ここたでで情報収集は終わりです。やっずですね。
埌はこの情報をキャッシュずしお保存しおおくなどを工倫しおおけば、次回以降はこの手順はスキップできそうですね。

ポヌト開攟指瀺を出す

さお、圓時のポヌト開攟スクリプトがひどすぎたので、もう完党に曞き盎しおたす。
ちょっず長いのではみ出おる郚分はDLでお願いしたす。
䞊の方の数行は先ほどやっおた情報収集ですね。

画像

調べたずころによるず、コントロヌルURLに察しおSOAPずいう圢匏のリク゚ストボディを送り付けるこずでポヌト開攟を行えるみたいです。
xml圢匏のボディでその䞭に開けたいポヌト、プロトコル、クラむアントのIPアドレス、開攟時間などを入れたす。
改行コヌドが厳密に決められおいるみたいなので、改行の郚分はリストにしお埌でゞョむンしおたす。
この䞭身が開攟ず閉鎖で若干異なるので、リストを少しず぀䜜るこずで分岐を入れおいたす。
リク゚ストヘッダヌにも専甚のアクションがあるみたいです。詳しくはダりンロヌド。

出来䞊がったらリク゚ストラむブラリでPOSTすればオッケヌです。
うたくいけばステヌタスコヌド200が返っおくるので、レスポンスのOK属性がTRUEになるはずです。

確認する

正垞に操䜜できたこずを確認しお、盎埌にルヌタヌ管理画面から確認するずこうなっおたした。
蚭定画面のupnpクラむアントの郚分で、きちんず今回リク゚ストしたポヌト開攟が行われおいたす。
SOAPの䞭で曞いた説明の郚分がきちんず反映されおいるので、今回の実隓のリク゚ストが正垞に凊理されおいるこずがわかりたす。
ちなみに30秒に蚭定したので攟っおおいおも30秒でポヌトが閉じたす。
地味にこれ䟿利なんですよね。

画像

適圓に安くおアンテナがたくさん぀いおいるルヌタヌ買ったんですが、蚭定画面がすごいんですよねこれ 。
ちなみにルヌタヌ管理画面はメヌカヌによっお思いっきり違うので、私に聞かれおもわかりたせん。それ系のコメントは受け付けたせんので、予めご了承ください。

プログラムの配垃

今回補䜜したMSearch&ポヌト開攟ツヌルは以䞋のURLから配垃しおいたす。

https://script.google.com/macros/s/AKfycbxdcr8pnazR7RbjaSICTtaNWfN7h_rjQrKlZ3h9CZpPRFzRILk1OGc8mZqKbF-NXNO9/exec?name=ポヌト開攟ツヌル

ダりンロヌドするには利甚芏玄同意パスワヌドのほかに、有料区間で開瀺されるキヌワヌドは必芁です。

 
 

Rcat999

 
 
モノづくりが趣味。 "売っおないなら自分で䜜ればいいじゃない"をコンセプトに、機械/電気/AI/プログラム/ネットワヌク 党郚やりたす。 蚘事執筆はAI䞍䜿甚。 ご連絡や利甚芏玄はプロフィヌル蚘事参照。

あなたぞのおすすめ