内部 IP のポートへのポート マップを指定できません
ただし、外部 IP を内部Linuxサーバーにマッピングしました。
しかし、VNC を使用して外部から内部のWindowsコンピューターに接続したいとも考えています。
それで私はこのプログラムを書きました、そして原理は次のようなものです
このプログラムは、リスニング アクションのために Linux サーバー上のポートを開き、外部接続がこのポートに接続されている場合、プログラムは内部 Windows VNC への別の接続を開き、外部パケットをそのままの状態で VNC 接続にスローします。 VNC 接続から返されたデータをそのまま外部ポートにスローします。
プログラムコード:
#!/usr/bin/php -q
<?php
$IP = '192.168.1.1' ; // Windows コンピューターの IP
$Port = '5900 ' //VNC が使用するポート
$ServerPort = '9999 ' //Linuxサーバーが外部で使用するポート
$ RemoteSocket = false //VNCのソケットに接続します。
関数SignalFunction & #40;$Signal)
& #123;
//これはメインプロセスのメッセージ処理関数です
global $PID ; //子プロセスのPID
スイッチ「$Signal」
& #123;
ケースSIGTRAP & #58;
ケースSIGTERM & #58;
// プログラムを終了するシグナルを受信します
もし& #40;$PID)
& #123;
// SIGTERM シグナルを Child に送信して、すぐに終了するように指示します。
posix_kill & #40;$PID,SIGTERM);
//ゾンビを避けるために子プロセスが終了するまで待ちます
pcntl_wait & #40;$ステータス);
& #125;
//メインプロセスが開いたソケットを閉じる
DestroySocket & #40;);
exit& #40;0); //メインプロセスを終了する
壊す;
ケースSIGCHLD & #58;
/*
子プロセスが終了すると、子プロセスは親に SIGCHLD シグナルを送信します。
親は SIGCHLD を受け取ると、子プロセスが終了したことを認識し、いくつかの終了アクションを実行する必要があります*/
unset& #40;$PID); //子プロセスが終了したことを示すために $PID をクリアします
pcntl_wait & #40;$Status); //ゾンビを避ける
壊す;
デフォルト& #58;
& #125;
& #125;
関数ChildSignalFunction & #40;$Signal)
& #123;
//これは子プロセスのメッセージ処理関数です
スイッチ「$Signal」
& #123;
ケースSIGTRAP & #58;
ケースSIGTERM & #58;
//子プロセスが終了メッセージを受信する
DestroySocket & #40;); //ソケットを閉じる
exit& #40;0); //子プロセスを終了する
デフォルト& #58;
& #125;
& #125;
関数ProcessSocket & #40;$ConnectedServerSocket)
& #123;
//子プロセスソケット処理関数
//$ConnectedServerSocket -> 外部接続ソケット
グローバル$ServerSocket 、 $RemoteSocket 、 $IP 、 $Port ;
$ServerSocket = $ConnectedServerSocket ;
declare& #40;ticks = 1); //この行を追加する必要があります。追加しないと、メッセージ処理関数を設定できません。
//メッセージ処理関数の設定
if& #40;!pcntl_signal(SIGTERM, "ChildSignalFunction"))
if& #40;!pcntl_signal(SIGTRAP, "ChildSignalFunction"))
//VNCに接続するソケットを作成
$RemoteSocket =ソケット_作成& #40;AF_INET、SOCK_STREAM、SOL_TCP);
// 内部 VNC に接続します
@ $RemoteConnected =ソケット接続& #40;$RemoteSocket,$IP,$Port);
if& #40;!$RemoteConnected) //VNC エンドに接続できません
//プログラムがブロックされないようにソケット処理をノンブロックに設定します
if& #40;!socket_set_nonblock($RemoteSocket))
if& #40;!socket_set_nonblock($ServerSocket))
一方「真実」
& #123;
//ここではプーリングを使用してデータを取得します
$NoRecvData = false ; //この変数は、外部接続がデータを読み取ったかどうかを判断するために使用されます。
$NoRemoteRecvData = false ; //この変数は、VNC 接続がデータを読み取ったかどうかを判断するために使用されます。
@ $RecvData =ソケット_読み取り& #40;$ServerSocket,4096,PHP_BINARY_READ);
//外部接続から 4096 バイトのデータを読み取ります
@ $RemoteRecvData =ソケット_読み取り& #40;$RemoteSocket,4096,PHP_BINARY_READ);
//vnc 接続から 4096 バイトのデータを読み取ります
if& #40;$RemoteRecvData==='')
& #123;
//VNC 接続が中断されたため、終了する時間になりました
echo "リモート接続を閉じますn" ;
戻る;
& #125;
if& #40;$RemoteRecvData===false)
& #123;
/*
nonblobk モードを使用しているため、ここでの状況は、vnc 接続に読み取るデータがないことです。
*/
$NoRemoteRecvData = true ;
//最後のエラーをクリア
socket_clear_error & #40;$RemoteSocket);
& #125;
if& #40;$RecvData==='')
& #123;
// 外部接続が中断されたため、終了する時間になりました
echo "クライアント接続を閉じますn" ;
戻る;
& #125;
if& #40;$RecvData===false)
& #123;
/*
nonblobk モードを使用しているため、ここでは外部接続から読み取ることができるデータがないという状況になります。
*/
$NoRecvData = true ;
//最後のエラーをクリア
socket_clear_error & #40;$ServerSocket);
& #125;
if& #40;$NoRecvData&&$NoRemoteRecvData)
& #123;
//外部接続にも VNC 接続にも読み取るデータがない場合、
//CPU リソースの長時間使用を避けるために、プログラムを 0.1 秒間スリープさせます。
usleep & #40;100000);
// 起動後、ソケットを読み取るためのプーリング アクションを続行します。
続く;
& #125;
//データを受信
if& #40;!$NoRecvData)
& #123;
//外部接続によるデータの読み取り
一方「真実」
& #123;
//外部接続から読み取ったデータをVNC接続に転送
@ $WriteLen =ソケットライト& #40;$RemoteSocket,$RecvData);
if& #40;$WriteLen===false)
& #123;
//ネットワーク伝送の問題により、現在データを書き込むことができません。
//0.1 秒間スリープしてから再試行します。
usleep & #40;100000);
続く;
& #125;
if& #40;$WriteLen===0)
& #123;
//リモート接続が中断されたため、プログラムを終了する必要があります
echo "リモート書き込み接続を閉じるn" ;
戻る;
& #125;
//外部接続から読み取られたデータが VNC 接続に完全に送信されると、このループは中断されます。
if& #40;$WriteLen==strlen($RecvData)) ブレーク;
//データを一度に送信できない場合は、すべてのデータが送信されるまで複数の送信に分割する必要があります。
$RecvData = substr & #40;$RecvData,$WriteLen);
& #125;
& #125;
if& #40;!$NoRemoteRecvData)
& #123;
//ここでは、VNC 接続から読み取られ、外部接続に戻されたデータを示します。
//原理は上記とほぼ同じなので、詳細は説明しません。
一方「真実」
& #123;
@ $WriteLen =ソケット_ライト& #40;$ServerSocket,$RemoteRecvData);
if& #40;$WriteLen===false)
& #123;
usleep & #40;100000);
続く;
& #125;
if& #40;$WriteLen===0)
& #123;
echo "リモート書き込み接続を閉じますn" ;
戻る;
& #125;
if& #40;$WriteLen==strlen($RemoteRecvData))
$RemoteRecvData = substr & #40;$RemoteRecvData,$WriteLen);
& #125;
& #125;
& #125;
& #125;
関数DestroySocket & #40;)
& #123;
//開いたソケットを閉じるために使用されます
グローバル$ServerSocket 、 $RemoteSocket ;
if& #40;$RemoteSocket)
& #123;
//VNC接続がすでに有効になっている場合
//ソケットを閉じる前にソケットをシャットダウンする必要があります。そうしないと、接続が閉じられたことが相手に伝わりません。
@socket_shutdown & # 40;$RemoteSocket,2);
socket_clear_error & #40;$RemoteSocket);
//ソケットを閉じる
ソケットクローズ& #40;$RemoteSocket);
& #125;
// 外部接続を閉じる
@socket_shutdown & # 40;$ServerSocket,2);
socket_clear_error & #40;$ServerSocket);
ソケットクローズ& #40;$ServerSocket);
& #125;
//これがプログラム全体の始まりであり、プログラムはここから実行を開始します
//まずここでフォークを実行します
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) die(「フォークできませんでした」);
//$PID が 0 でない場合、これは親プロセスであることを意味します
//$PID は子プロセスです
//これは親プロセスです。自分で終了し、子をデーモンにします。
if& #40;$PID)「デーモン PID:$PIDn」);
//ここからデーモンモードが実行されます。
//現在のプロセスをターミナルから切り離し、デーモンモードに入る
if& #40;!posix_setsid()) die(「端末から接続解除できませんでしたn」);
//デーモンのメッセージ処理関数を設定する
& #40;ティック = 1);を宣言します
if& #40;!pcntl_signal(SIGTERM, "SignalFunction")) die("エラー!!!n");
if& #40;!pcntl_signal(SIGTRAP, "SignalFunction")) die("エラー!!!n");
if& #40;!pcntl_signal(SIGCHLD, "SignalFunction")) die("エラー!!!n");
//外部接続用のソケットを確立します
$ServerSocket =ソケット_作成& #40;AF_INET、SOCK_STREAM、SOL_TCP);
//外部接続監視用の IP とポートを設定します。IP フィールドを 0 に設定します。これは、すべてのインターフェイスの IP をリッスンすることを意味します。
if& #40;!socket_bind($ServerSocket,0,$ServerPort)) die(「ソケットをバインドできません!n」);
// ポートのリッスンを開始します
if& #40;!socket_listen($ServerSocket)) die(「聞くことができません!n」);
//ソケットをノンブロックモードに設定
if& #40;!socket_set_nonblock($ServerSocket)) die(「サーバーソケットをブロックに設定できません!n」);
// 現在子プロセスが存在しないことを示す $PID 変数をクリアします
設定を解除& #40;$PID);
一方「真実」
& #123;
//プーリングモードに入り、1秒ごとに接続があるかどうかを確認します。
睡眠& #40;1);
// 接続が入っているかどうかを確認する
@ $ConnectedServerSocket =ソケット_accept & #40;$ServerSocket);
if& #40;$ConnectedServerSocket!==false)
& #123;
//誰かが入ってくる
// 接続を処理するために子プロセスを開始します
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) die(「フォークできませんでした」);
if& #40;$PID) continue;//これはデーモン プロセスです。監視を続けます。
//ここから子プロセスが始まります
//Socketで関数を実行
プロセスソケット& #40;$ConnectedServerSocket);
//Socketの処理後、Socketを終了する
DestroySocket & #40;);
//子プロセスを終了する
終了& #40;0);
& #125;
& #125;
?>