Ich schreibe ein Programm, das prüfen soll, ob bestimmte UDP-Ports "offen" sind.
Mir ist klar, dass UDP ein verbindungsloses Protokoll ist, d.h. im Unterschied zu TCP findet bei UDP kein Verbindungsaufbau statt, sondern es werden einfach einzelne Pakete geschickt. Das bedeutet, wenn ich testweise ein Paket an einen UDP-Port schicke und der Ziel-Port ist tatsächlich "offen", d.h. ein Programm lauscht auf diesem Port, dann werde ich i.d.R. keine Antwort bekommen. Denn das Programm wird meine Test-Nachricht nicht verstehen und einfach ignorieren. Der interessantere Fall ist der, wenn der UDP-Port "geschlossen" ist, d.h. wenn auf dem Ziel-Port kein Programm lauscht. In diesem Fall verweigert der Host die Annahme des UDP-Pakets und signalisiert das an den Absender, mit einem ICMP-Paket mit Code 3 ("Port Unreachable"). Der Java-Socket wirft in diesem Fall eine
So zumindest die Theorie:
Leider scheint das bei mir überhaupt nicht zu klappen! Ich bekomme immer nach längerer Zeit eine
Mein Code sieht so aus:
Ausgabe:
Danke für Eure Hilfe!
Mir ist klar, dass UDP ein verbindungsloses Protokoll ist, d.h. im Unterschied zu TCP findet bei UDP kein Verbindungsaufbau statt, sondern es werden einfach einzelne Pakete geschickt. Das bedeutet, wenn ich testweise ein Paket an einen UDP-Port schicke und der Ziel-Port ist tatsächlich "offen", d.h. ein Programm lauscht auf diesem Port, dann werde ich i.d.R. keine Antwort bekommen. Denn das Programm wird meine Test-Nachricht nicht verstehen und einfach ignorieren. Der interessantere Fall ist der, wenn der UDP-Port "geschlossen" ist, d.h. wenn auf dem Ziel-Port kein Programm lauscht. In diesem Fall verweigert der Host die Annahme des UDP-Pakets und signalisiert das an den Absender, mit einem ICMP-Paket mit Code 3 ("Port Unreachable"). Der Java-Socket wirft in diesem Fall eine
PortUnreachableException
, so dass wir erkennen können, dass der Port "geschlossen" ist.So zumindest die Theorie:
6.5 ICMP Port Unreachable Error
[...]
One rule of UDP is that if it receives a UDP datagram and the destination port does not correspond to a port that some process has in use, UDP responds with an ICMP port unreachable [Code 3]. We can force a port unreachable using the TFTP client. The well-known UDP port for the TFTP server to be reading from is 69. But most TFTP client programs allow us to specify a different port using the connect command. We use this to specify a port of 8888. [...] An ICMP port unreachable is immediately returned. — http://isp.vsi.ru/library/Networking/TCPIPIllustrated/icmp_int.htm#6_5
Class PortUnreachableException
Signals that an ICMP Port Unreachable message has been received on a connected datagram.
Leider scheint das bei mir überhaupt nicht zu klappen! Ich bekomme immer nach längerer Zeit eine
SocketTimeoutException
, aber niemals eine PortUnreachableException
, auch wenn der Ziel-Port mit 100% Sicherheit definitiv "geschlossen" ist. Habe es bereits mit verschiedenen Rechnern, sowohl im Internet als auch im lokalen Netz versucht. Im lokalen Netz weiß ich zu 100%, dass weder mein UDP-Anfrage-Paket noch das ICMP-Antwort-Paket irgenwie "gefilter" werden können. Die Rechner sind ja direkt über ein lokales Switch verbunden, d.h. da ist keine Firewall oder irgendwas in der Art dazwischen. Es ist auch keine Software-Firewall oder so installiert. Trotzdem konnte bisher nie eine PortUnreachableException
von dem Java-Socket bekommen. Werde langsam etwas wahnsinnig damit. Was mach ich falsch? Oder ist das vielleicht ein bekannter Bug in Java? Mein Code sieht so aus:
Java:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.HexFormat;
public class UdpTester {
private static final HexFormat hexfmt = HexFormat.of();
public static void main(final String[] args) {
final InetAddress address;
try {
address = InetAddress.getByName("www.example.com");
System.err.println("Address: " + address);
} catch (UnknownHostException e) {
System.err.println("Failed to resovle hostname: " + e.toString());
return;
}
for (int port = 1; port <= 1024; ++port ) {
try {
testUdpPort(address, port);
} catch(final IOException e) {
System.err.printf("Error while testing port %d: %s%n", port, e.toString());
}
}
}
private static void testUdpPort(final InetAddress address, final int port) throws IOException {
final DatagramSocket udpSocket = new DatagramSocket();
try {
udpSocket.setSoTimeout(30000);
// Send packet
try {
final byte[] message = "hello".getBytes(StandardCharsets.ISO_8859_1);
final DatagramPacket outbound = new DatagramPacket(message, message.length, address, port);
udpSocket.send(outbound);
} catch (final SocketTimeoutException e) {
System.err.printf("Error while sending to port %d: %s%n", port, e.toString());
}
// Receive response
try {
final byte[] recvBuffer = new byte[65535];
final DatagramPacket inbound = new DatagramPacket(recvBuffer, recvBuffer.length);
udpSocket.receive(inbound); // <-- this shall throw PortUnreachableException, if the target port is closed !!!
System.err.println("Response: " + hexfmt.formatHex(inbound.getData(), 0, inbound.getLength()));
} catch (final SocketTimeoutException e) {
System.err.printf("Error while receiving from port %d: %s%n", port, e.toString());
}
} finally {
try {
udpSocket.close();
} catch(Exception e) { }
}
}
}
Ausgabe:
Code:
Address: www.example.com/93.184.216.34
Error while receiving from port 1: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 2: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 3: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 4: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 5: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 6: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 7: java.net.SocketTimeoutException: Receive timed out
Error while receiving from port 8: java.net.SocketTimeoutException: Receive timed out
Danke für Eure Hilfe!
Zuletzt bearbeitet: