Es kann keine Portzuordnung für einen Port einer internen IP angegeben werden
Aber ich habe die externe IP dem internen Linux- Server zugeordnet.
Ich möchte aber auch VNC verwenden, um von außen eine Verbindung zu einem internen Windows -Computer herzustellen.
Also habe ich dieses Programm geschrieben und das Prinzip ist so
Dieses Programm öffnet einen Port auf dem Linux-Server für Abhöraktionen. Wenn die externe Verbindung mit diesem Port verbunden ist, öffnet das Programm eine weitere Verbindung zum internen Windows-VNC und leitet die externen Pakete intakt an die VNC-Verbindung weiter wirft die von der VNC-Verbindung zurückgegebenen Daten intakt zurück an den externen Port.
Programmcode:
#!/usr/bin/php -q
<?php
$IP = '192.168.1.1' ; //IP des Windows-Computers
$Port = '5900' ; //Von VNC verwendeter Port
$ServerPort = '9999' ; //Vom Linux-Server extern verwendeter Port
$RemoteSocket = false ; //Mit dem Socket von VNC verbinden
Funktion SignalFunction & #40;$Signal)
& #123;
//Dies ist die Nachrichtenverarbeitungsfunktion des Hauptprozesses
global $PID ; //PID des untergeordneten Prozesses
Schalter & #40;$Signal)
& #123;
Fall SIGTRAP & #58;
Fall SIGTERM & #58;
//Empfangen Sie das Signal, um das Programm zu beenden
if& #40;$PID)
& #123;
//Sende ein SIGTERM-Signal an das Kind, um es schnell zu beenden.
posix_kill & #40;$PID,SIGTERM);
//Warten Sie, bis der untergeordnete Prozess beendet ist, um Zombies zu vermeiden
pcntl_wait & #40;$Status);
& #125;
//Schließe den vom Hauptprozess geöffneten Socket
DestroySocket & #40;);
exit& #40;0); //Beenden Sie den Hauptprozess
brechen;
Fall SIGCHLD & #58;
/*
Wenn der Child-Prozess endet, sendet Child ein SIGCHLD-Signal an Parent
Wenn das übergeordnete Element SIGCHLD empfängt, weiß es, dass der untergeordnete Prozess beendet wurde und einige Abschlussmaßnahmen ergreifen sollte*/
unset& #40;$PID); //Löschen Sie $PID, um anzuzeigen, dass der untergeordnete Prozess beendet wurde
pcntl_wait & #40;$Status); //Zombie meiden
brechen;
Standard& #58;
& #125;
& #125;
Funktion ChildSignalFunction & #40;$Signal)
& #123;
//Dies ist die Nachrichtenverarbeitungsfunktion des untergeordneten Prozesses
Schalter & #40;$Signal)
& #123;
Fall SIGTRAP & #58;
Fall SIGTERM & #58;
//Der untergeordnete Prozess empfängt die Endnachricht
DestroySocket & #40;);
exit& #40;0); //Untergeordneten Prozess beenden
Standard& #58;
& #125;
& #125;
Funktion ProcessSocket & #40;$ConnectedServerSocket)
& #123;
//Socket-Verarbeitungsfunktion des untergeordneten Prozesses
//$ConnectedServerSocket -> Extern verbundener Socket
global $ServerSocket , $RemoteSocket , $IP , $Port ;
$ServerSocket = $ConnectedServerSocket ;
deklarieren& #40;ticks = 1); //Diese Zeile muss hinzugefügt werden, sonst kann die Nachrichtenverarbeitungsfunktion nicht eingestellt werden.
//Nachrichtenverarbeitungsfunktion festlegen
if& #40;!pcntl_signal(SIGTERM, "ChildSignalFunction"))
if& #40;!pcntl_signal(SIGTRAP, "ChildSignalFunction"))
//Erstelle einen mit VNC verbundenen Socket
$RemoteSocket = socket_create & #40;AF_INET, SOCK_STREAM,SOL_TCP);
//Mit dem internen VNC verbinden
@ $RemoteConnected = socket_connect & #40;$RemoteSocket,$IP,$Port);
if& #40;!$RemoteConnected) //Verbindung zum VNC-Ende nicht möglich
// Setzen Sie die Socket-Verarbeitung auf „Nicht blockieren“, um zu verhindern, dass das Programm blockiert wird
if& #40;!socket_set_nonblock($RemoteSocket))
if& #40;!socket_set_nonblock($ServerSocket))
while& #40;true)
& #123;
//Hier verwenden wir Pooling, um Daten zu erhalten
$NoRecvData = false ; //Diese Variable wird verwendet, um festzustellen, ob die externe Verbindung Daten gelesen hat.
$NoRemoteRecvData = false ; //Diese Variable wird verwendet, um zu bestimmen, ob die VNC-Verbindung Daten gelesen hat.
@ $RecvData = socket_read & #40;$ServerSocket,4096,PHP_BINARY_READ);
//4096 Byte Daten von der externen Verbindung lesen
@ $RemoteRecvData = socket_read & #40;$RemoteSocket,4096,PHP_BINARY_READ);
//4096 Byte Daten aus der VNC-Verbindung lesen
if& #40;$RemoteRecvData==='')
& #123;
//VNC-Verbindung ist unterbrochen, es ist Zeit zu beenden
echo "Remote-Verbindung schließenn" ;
zurückkehren;
& #125;
if& #40;$RemoteRecvData===false)
& #123;
/*
Da wir den Nicht-Blobk-Modus verwenden, liegt hier die Situation vor, dass die VNC-Verbindung keine Daten zum Lesen hat.
*/
$NoRemoteRecvData = true ;
//Letzten Fehler löschen
socket_clear_error & #40;$RemoteSocket);
& #125;
if& #40;$RecvData==='')
& #123;
//Die externe Verbindung ist unterbrochen, es ist Zeit zu beenden
echo „Client-Verbindung schließenn“ ;
zurückkehren;
& #125;
if& #40;$RecvData===false)
& #123;
/*
Da wir den Non-Blobk-Modus verwenden, sind hier keine Daten zum Lesen über die externe Verbindung verfügbar.
*/
$NoRecvData = true ;
//Letzten Fehler löschen
socket_clear_error & #40;$ServerSocket);
& #125;
if& #40;$NoRecvData&&$NoRemoteRecvData)
& #123;
//Wenn weder die externe Verbindung noch die VNC-Verbindung Daten zum Lesen haben,
// Lassen Sie das Programm 0,1 Sekunden lang ruhen, um eine langfristige Nutzung der CPU-Ressourcen zu vermeiden
usleep & #40;100000);
// Setzen Sie nach dem Aufwachen die Pooling-Aktion fort, um den Socket zu lesen
weitermachen;
& #125;
//Recv-Daten
if& #40;!$NoRecvData)
& #123;
//Externe Verbindung liest Daten
while& #40;true)
& #123;
// Übertragen Sie die von der externen Verbindung gelesenen Daten an die VNC-Verbindung
@ $WriteLen = socket_write & #40;$RemoteSocket,$RecvData);
if& #40;$WriteLen===false)
& #123;
//Aufgrund von Netzwerkübertragungsproblemen können Daten derzeit nicht geschrieben werden.
//0,1 Sekunden lang schlafen, bevor es erneut versucht wird.
usleep & #40;100000);
weitermachen;
& #125;
if& #40;$WriteLen===0)
& #123;
//Die Remote-Verbindung ist unterbrochen, das Programm sollte beendet werden
echo "Remote-Schreibverbindung schließenn" ;
zurückkehren;
& #125;
//Wenn die von der externen Verbindung gelesenen Daten vollständig an die VNC-Verbindung gesendet wurden, wird diese Schleife unterbrochen.
if& #40;$WriteLen==strlen($RecvData))
//Wenn die Daten nicht gleichzeitig gesendet werden können, müssen sie in mehrere Übertragungen aufgeteilt werden, bis alle Daten gesendet sind.
$RecvData = substr & #40;$RecvData,$WriteLen);
& #125;
& #125;
if& #40;!$NoRemoteRecvData)
& #123;
//Hier sind die Daten, die von der VNC-Verbindung gelesen und dann zurück an die externe Verbindung übertragen werden.
//Das Prinzip ist fast das gleiche wie oben und ich werde nicht noch einmal auf Details eingehen.
while& #40;true)
& #123;
@ $WriteLen = socket_write & #40;$ServerSocket,$RemoteRecvData);
if& #40;$WriteLen===false)
& #123;
usleep & #40;100000);
weitermachen;
& #125;
if& #40;$WriteLen===0)
& #123;
echo „Remote-Schreibverbindung schließenn“ ;
zurückkehren;
& #125;
if& #40;$WriteLen==strlen($RemoteRecvData))
$RemoteRecvData = substr & #40;$RemoteRecvData,$WriteLen);
& #125;
& #125;
& #125;
& #125;
Funktion DestroySocket & #40;)
& #123;
//Wird verwendet, um den geöffneten Socket zu schließen
global $ServerSocket , $RemoteSocket ;
if& #40;$RemoteSocket)
& #123;
//Wenn die VNC-Verbindung bereits aktiviert ist
// Der Socket muss heruntergefahren werden, bevor der Socket geschlossen wird, sonst weiß die andere Partei nicht, dass Sie die Verbindung geschlossen haben.
@ socket_shutdown & #40;$RemoteSocket,2);
socket_clear_error & #40;$RemoteSocket);
//Socket schließen
socket_close & #40;$RemoteSocket);
& #125;
//Externe Verbindungen schließen
@ socket_shutdown & #40;$ServerSocket,2);
socket_clear_error & #40;$ServerSocket);
socket_close & #40;$ServerSocket);
& #125;
//Dies ist der Anfang des gesamten Programms und die Ausführung des Programms beginnt hier
//Führen Sie hier zunächst einen Fork aus
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) die(„konnte nicht gegabelt werden“);
//Wenn $PID nicht 0 ist, bedeutet dies, dass es sich um einen übergeordneten Prozess handelt
//$PID ist ein untergeordneter Prozess
//Dies ist der übergeordnete Prozess. Beenden Sie ihn selbst und lassen Sie das Kind zum Daemon werden.
if& #40;$PID) die("Daemon PID:$PIDn");
//Von hier an wird der Daemon-Modus ausgeführt.
//Trennen Sie den aktuellen Prozess vom Terminal und wechseln Sie in den Daemon-Modus
if& #40;!posix_setsid()) die("konnte nicht vom Terminal getrennt werdenn");
//Legen Sie die Nachrichtenverarbeitungsfunktion des Daemons fest
deklarieren& #40;ticks = 1);
if& #40;!pcntl_signal(SIGTERM, "SignalFunction")) die("Error!!!n");
if& #40;!pcntl_signal(SIGTRAP, "SignalFunction")) die("Error!!!n");
if& #40;!pcntl_signal(SIGCHLD, "SignalFunction")) die("Error!!!n");
//Stellen Sie einen Socket für eine externe Verbindung her
$ServerSocket = socket_create & #40;AF_INET, SOCK_STREAM,SOL_TCP);
//Stellen Sie die IP und den Port für die externe Verbindungsüberwachung ein. Setzen Sie das IP-Feld auf 0, was bedeutet, dass die IPs aller Schnittstellen überwacht werden.
if& #40;!socket_bind($ServerSocket,0,$ServerPort)) die("Cannot Bind Socket!n");
//Beginnen Sie mit dem Abhören des Ports
if& #40;!socket_listen($ServerSocket)) die("Cannot Listen!n");
//Socket auf Nichtblockmodus setzen
if& #40;!socket_set_nonblock($ServerSocket)) die("Server Socket kann nicht auf Block gesetzt werden!n");
//Löschen Sie die Variable $PID, um anzuzeigen, dass derzeit kein untergeordneter Prozess vorhanden ist
nicht gesetzt& #40;$PID);
while& #40;true)
& #123;
//In den Pooling-Modus wechseln und alle 1 Sekunde prüfen, ob eine Verbindung besteht.
Schlaf & #40;1);
//Überprüfen Sie, ob eine Verbindung hergestellt wird
@ $ConnectedServerSocket = socket_accept & #40;$ServerSocket);
if& #40;$ConnectedServerSocket!==false)
& #123;
//Jemand kommt herein
//Starten Sie einen untergeordneten Prozess, um die Verbindung zu verarbeiten
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) die(„konnte nicht gegabelt werden“);
if& #40;$PID) continue;//Dies ist der Daemon-Prozess, weiterhin überwachen.
//Hier ist der Beginn des Child-Prozesses
//Führen Sie die Funktion im Socket aus
ProcessSocket & #40;$ConnectedServerSocket);
// Nach der Verarbeitung des Sockets den Socket beenden
DestroySocket & #40;);
//Untergeordneten Prozess beenden
Ausgang& #40;0);
& #125;
& #125;
?>