UDP Port bestimmen | Windows, MAC, Linux...

Dit_

Bekanntes Mitglied
Hallo,

ist es möglich einen für UDP bestimmten Port festzustellen und zwar mit einer Methode die auf verschiedenen OS funktionieren würde?

Ich brauche das für eine ProjektArbeit, da muss man in einer XML-Datei den Port angeben, manchmal weiss aber der Benutzer nicht welcher port im Netz (einer Schule oder Organisation) freigegeben ist. Ich weiss man kann RZ fragen, aber vielleicht kann man einfach eine Suchfunktion anbieten 🙂


Habe im Netz folgende Methode gefunden

Java:
public static void main(String[] args) {
		for (int port = 1024; port <= 65535; port++) {
			try {
				DatagramSocket server = new DatagramSocket(port);
				server.close();
				System.out.println("OK: " + port);
			} catch (SocketException ex) {
				System.out.println("There is a server on port " + port + ".");
			}
		}
	}

Was sagen die Profis?

Danke schon mal
 
ist es möglich einen für UDP bestimmten Port festzustellen...
Nicht sehr sauber. Portscanner beschießen eine Zieladresse mit Paketen auf allen Ports und testen, ob eventuell eingehende Pakete zu einem versandten Paket passen.

In Deinem Fall wäre das nicht besonders "höflich" und auch nicht 100%-ig sicher, da das "U" in UDP nun mal für unreliable steht. Wenn Du das Antwortverhalten und Format der Pakete kennst, ließe sich vielleicht was machen, was einigermaßen funktioniert. Der Code da unten scheint ganz nett zu klappen:

Code:
PortscanDemo
kann einen laufenden DNS Server erkennen. Für Deine Zwecke kannst Du die Klasse
Code:
DNSSinglePortScanner
Vorlage zu verwenden; musst nur
  • Den Konstruktor überladen
  • Code:
    genUDPPayload()
    überladen; gibt die byte Vorlage für die UDP Pakete zurück.
  • Code:
    verifyReturnedPayload()
    überladen; testet ob ein empfangenes Paket ein gültiges Antwortpaket sein kann.

Der Code der Basisklasse ist an etlichen Stellen verbesserungswürdig, z. B. kann man
  • den/die Timeout(s) schöner implementieren
  • Exceptions besser behandeln
  • das blocking fixen, da
    Code:
    receive()
    ständig
    Code:
    null
    -s zutückliefert. (Keine Ahnung wieso...)
  • eine Abbruchfunktion für den Scan einbauen, anstatt nach 10 Sekunden automatisch zu sterben
  • intervallartiges Senden/Empfangen von Paketen, Z. B. nicht mehr als 100 auf einmal, damit die Firewalls nicht denken, man wolle eine DoS-Attacke starten, usw...

Java:
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

interface PortScanner {
	static final int INVALID_PORT = -1;
	int scan() throws IOException;
};

abstract class AbstractUDPSinglePortScanner implements PortScanner {

	private final int portMin;
	private final int portMax;
	private final InetAddress dest;
	
	private static final int TIMEOUT_SECONDS=10;

	protected abstract byte[] genUDPPayload();

	protected abstract boolean verifyReturnedPayload(byte[] payload);

	protected AbstractUDPSinglePortScanner(String hostName, int portMin, int portMax)
			throws IOException {

		this.portMin = Math.min(portMin, portMax);
		this.portMax = Math.max(portMin, portMax);

		dest = Inet4Address.getByName(hostName);
	}

	@Override
	public final int scan() throws IOException {

		final DatagramChannel ch = DatagramChannel.open();
		ch.configureBlocking(true);

		final ExecutorService exs = Executors.newSingleThreadExecutor(); 
		final Future<Integer> f = exs.submit(
			new Callable<Integer>() {

				@Override
				public Integer call() throws Exception {
					final byte[] buffer = new byte[1024];
					final ByteBuffer bb = ByteBuffer.wrap(buffer);
					
					while (true) {
						final SocketAddress soa = ch.receive(bb);

						if (soa != null) {
							bb.flip();

							if (soa instanceof InetSocketAddress) {
								final InetSocketAddress isa = (InetSocketAddress) soa;
								if (isa.getAddress().equals(dest)
										&& verifyReturnedPayload(buffer)) {
									return isa.getPort();
								}
							}
						}
					}
				}
			});
		exs.shutdown();
		
		for (int port = portMin; port <= portMax; port++) {
			ch.send(ByteBuffer.wrap(this.genUDPPayload()), 
				new InetSocketAddress(dest, port));
		}

		try {
			if(!exs.awaitTermination(TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
				f.cancel(true);
				return PortScanner.INVALID_PORT;
			} 
			
			return f.get();
		} catch (InterruptedException e) {
			return PortScanner.INVALID_PORT;
		} catch (ExecutionException e) {
			return PortScanner.INVALID_PORT;
		}
	}
}

class DNSSinglePortScanner extends AbstractUDPSinglePortScanner {
	
	private static final byte dns_google_de[] = { 
		0x7d, (byte) 0x9f, 0x01, 0x00, 0x00,
		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
		0x00, 0x03, 0x77, 0x77, 0x77, 0x06, 
		0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 
		0x02, 0x64, 0x65, 0x00, 0x00, 0x01, 
		0x00, 0x01 };

	public DNSSinglePortScanner(String hostName, int portMin, int portMax)
			throws IOException {
		super(hostName, portMin, portMax);
	}

	@Override
	protected byte[] genUDPPayload() {		
		return dns_google_de;
	}

	@Override
	protected boolean verifyReturnedPayload(byte[] payload) {
		return true;
	}	
}

public class PortscanDemo {

	public static void main(String[] args) throws IOException {
		
		final PortScanner ps = new DNSSinglePortScanner("208.67.222.222", 20, 70);
		final int port = ps.scan();
		System.out.println("DNS auf port: "+(port != PortScanner.INVALID_PORT ? port : "(nicht gefunden)"));
	}
}

Habe im Netz folgende Methode gefunden
Das hilft Dir nicht weiter. Hier wird getestet, ob auf Deiner eigenen Maschine ein Prozess auf einem Port lauscht, wenn das berhaupt so klappt.
 
Zuletzt bearbeitet:

Zurück
Oben