PythonのSocketで、ルーターの異なる外部機器からの通信ができない


socketのTCP通信を用いるコードを書いており、同じグローバルIPアドレスの別機器同士（その場合はグローバルIPアドレスではなくローカルIPアドレスをclient.pyで使います）で以下のことを行ったときは成功したのですが、外部のpcを接続させようとしても失敗してしまいます。どうすればいいのでしょうか。

僕のmacOS14.0でserver.pyを、友人のWindows10でclient.pyを、python3.11.5を用いて実行しました。互いのpcのルーターは異なりますし、勿論IPアドレスも異なります。僕のmacOSでは、54321を番号としてポート開放しました（ポート開放は確実に成功しています）。しかし、いざ僕のpcでserver.pyを実行したあとに友人のpcでclient.pyを実行すると、client.pyの方で以下のエラーが吐かれます。

ファイヤーウォールは両pcとも無効になっています。回線もよいはずです。

stack overflowで質問をするのは今回が初めてなので、足りない情報などありましたらお申し付けください。

※追記1  
「ファイヤーウォールは両pcとも無効になっています。」と書きましたが、もう一度確かめてみると、友人のpcで外部のファイヤーウォールソフトが動いていたので無効にしました。が、そのあとコードを実行しても結果は一切変わりませんでした。  
※追記2  
使用しているWiFiルーターは、BUFFALOのWXR-2533DHP2（https://www.buffalo.jp/product/detail/wxr-2533dhp2.html
）です。ポート開放は公式サイト（https://www.buffalo.jp/support/faq/detail/15022.html
）の順序に沿って行いました。

[code]

    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    TimeoutError: [WinError 10060] 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした
    。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。
    
[/code]

＜server.py＞

[code]

    import socket
    
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    with server_socket:
        server_socket.bind(('0.0.0.0', 54321))
        server_socket.listen(1)
        
        client_socket, client_address = server_socket.accept()
        
        with client_socket:
            text_binary = client_socket.recv(1024)
            print(text_binary.decode('utf-8'))
    
[/code]

＜client.py＞

[code]

    import socket
    
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    with client_socket:
        client_socket.connect(('server.pyを実行するpcのグローバルIPアドレス', 54321))
        client_socket.send(b'hello')
    
[/code]




事実としては「接続がタイムアウトした」しかないので、これだけでは原因が何か、対策は何かを回答するのは無理です。(ルータの設定やファイヤーウォールの状況など書かれてますが、経験上「自己申告」は事実と異なることがよくあるので裏付けとなる情報がない場合はあまり信用できないのです)

1つずつ確認していく方が早いのですが、それはこのサイトの趣旨ではないので、総論的な切り分け方法を書いときます。

# なるべく制限のない環境で試す

「自宅で」というのは切り分けには最悪な環境で、ルータの設定がどうとかプロバイダ側でNATされてるとかへんなセキュリティが入ってるとか利用者固有の環境も考慮に含めないといけなくなります。なので、グローバルIPアドレスが直接割り振られてる環境でテストしましょう。

クラウドはクラウドでそっちの癖があるので、時間払いができるVPSが一番いいです。

# いろいろな組み合わせを試す

問題があるのはサーバ側かもしれませんしクライアント側かもしれませんし両方かもしれません。

サーバ側\クライアント側 | 本番 | 仮環境  
---|---|---  
本番 | ○or× | ○or×  
仮環境 | ○or× | ○or×  
  
# 別のポート/プログラムも試す

HTTPなど既知で制限がかかってなさそうなポートでも確認しましょう。自作のプログラムとと、既知のサーバソフトウェア(HTTPならIIS/Apache/nginx)の両方で試すとよいです。

クライアント側もtelnet(プログラムの方)とかで接続してみて試してください。

# 結果をまとめる

結果をまとめると、だいたいどこが悪いのか切り分けがつきます。  
例えば、サーバ側をVPSにしたらつながる、なら自宅の環境が何か引っかかってるな、ということになります。(ただこの場合その先に進むのはまた面倒なのですが)

