Öffentliche IP-Adresse: Unterschied zwischen den Versionen

Aus FHEMWiki
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 41: Zeile 41:


== Fritzbox nutzen ==
== Fritzbox nutzen ==
=== Reguläres Device nutzen ===
Wird eine Fritzbox als Router in das Internet verwendet, kann man die öffentliche IP sehr einfach vom Router abfragen. Der Vorteil dieser Lösung besteht darin, dass kein externer Dienst abgefragt werden muss:<syntaxhighlight lang="perl">
Wird eine Fritzbox als Router in das Internet verwendet, kann man die öffentliche IP sehr einfach vom Router abfragen. Der Vorteil dieser Lösung besteht darin, dass kein externer Dienst abgefragt werden muss:<syntaxhighlight lang="perl">
defmod Fritzbox FRITZBOX 192.168.123.123
defmod Fritzbox FRITZBOX 192.168.123.123
Zeile 52: Zeile 55:
  <code>box_ipv6_Extern</code>
  <code>box_ipv6_Extern</code>
  <code>box_ipv6_Prefix</code>
  <code>box_ipv6_Prefix</code>
=== Spezielle Abfrage der Fritzbox für Sonderfälle ===
In einigen Fällen stellt das Fritzbox Device nicht die passenden Readings bereit (zum Beispiel bei einer FB 6660 cable). Da in solchen Fällen CGNAT/DS-Lite eine IPv4 Abfrage vom Internet aus auf FHEM verhindert ist nur die öffentlich erreichbare IPv6 Adresse von Interesse (=GUA).
Es steht zur Zeit nur ein BASH Skript bereit ({{Link2Forum|Topic=141872|Message=1343341|LinkText=Quelle}}):<syntaxhighlight lang="bash">
#!/bin/bash
FRITZ_USER="<USER>"
FRITZ_PASS="<PASS>"
FRITZ_HOSTNAME="<HOST>"
FRITZ_IPV6_GUA=$(curl -s --max-time 10 \
    --anyauth --user "${FRITZ_USER}:${FRITZ_PASS}" \
    http://${FRITZ_HOSTNAME}:49000/upnp/control/wanipconnection1 \
    -H "Content-Type: text/xml; charset="utf-8"" \
    -H "SoapAction:urn:dslforum-org:service:WANIPConnection:1#GetExternalIPAddress" \
    -d "<?xml version='1.0' encoding='utf-8'?> <s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'> <s:Body> <u:GetExternalIPAddress xmlns:u='urn:dslforum-org:service:WANIPConnection:1'></u:GetExternalIPAddress> </s:Body> </s:Envelope>" | egrep -o "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?")
if [ -z "$FRITZ_IPV6_GUA" ]; then
    echo "Error! Can't get IPv6 GUA from FRITZ!Box"
    exit 0
else
    echo "FRITZ!Box IPv6 GUA is: $FRITZ_IPV6_GUA"
fi
</syntaxhighlight>


== STUN Server nutzen ==
== STUN Server nutzen ==
Zeile 66: Zeile 94:


Weitere Details und Diskussion: https://forum.fhem.de/index.php?topic=141872.msg1343225#msg1343225
Weitere Details und Diskussion: https://forum.fhem.de/index.php?topic=141872.msg1343225#msg1343225
== IPs des FHEM Servers ermitteln (ohne Link-Local, Docker, etc) ==
Sofern der FHEM Server bereits eine öffentliche IP hat, kann man diese von den lokalen Netzwerkinterfaces abfragen. Mit wenigen Abhängigkeiten geht dies unter typischen Linux-Distributionen wie Debian Buster, Bullseye, Bookworm oder aktueller mit:<syntaxhighlight lang="perl">
define LocalIPs at +*00:01:00 {
my $hash = $defs{$SELF};
my (@ipv4, @ipv6);
#Abfragen der IP Adressen mittels CLI:
my $json = qx(ip -j addr show scope global);
my $data = decode_json($json);
   
for my $iface (@$data) {
for my $addr (@{$iface->{addr_info} || []}) {
next unless $addr->{local};
if ($addr->{family} eq 'inet') {
push @ipv4, $addr->{local};
} elsif ($addr->{family} eq 'inet6') {
push @ipv6, $addr->{local};
}
}
}
readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "allIPv4", join(',', @ipv4));
readingsBulkUpdate($hash, "allIPv6", join(',', @ipv6));
readingsEndUpdate($hash, 1);
}
attr LocalIPs alignTime 00:00:00
attr LocalIPs event-on-change-reading .*
attr LocalIPs stateFormat IPv4: allIPv4<br />IPv6: allIPv6
</syntaxhighlight>

Aktuelle Version vom 17. Juni 2025, 07:27 Uhr

Einleitung

In FHEM kann die aktuell verwendete öffentliche IP-Adresse (IPv4/IPv6) auf verschiedene Arten ermittelt werden. Eine Methode ist der Abruf über externe Webdienste. Es kann auch auf lokale Router-Informationen (z. B. Fritzbox) oder systemnahe Module (z.B. STUN) zurückgegriffen werden.

HTTPMOD-Definition zum ermitteln der öffentlichen IPv4 und IPv6 via HTTPS-Webdienst

Die öffentliche IP kann man mit Webdiensten ermitteln, die einem die IPv4 und/oder IPv6 anzeigen mit der die Seite abgerufen wird:

defmod PublicIP HTTPMOD https://ipwho.de/json/ 600
attr PublicIP extractAllJSON 1

Ein Abfrageintervall von 300 bis 600 Sekunden (5 bis 10 Minuten) wird empfohlen – häufigere Abfragen belasten die externen Dienste unnötig.

Weitere Dienste

Getestete Dienste zum ermitteln der öffentlichen IP via HTTPS
Anbieter Adresse Zuletzt erfolgreich getestet im Jahr
ipify.org https://api64.ipify.org/?format=json 2025
ipwho.de https://ipwho.de/json/ 2025
ipinfo.io https://ipinfo.io/json/ 2025
myip.com https://api.myip.com/ 2025
ident.me https://a.ident.me/json 2025

Fritzbox nutzen

Reguläres Device nutzen

Wird eine Fritzbox als Router in das Internet verwendet, kann man die öffentliche IP sehr einfach vom Router abfragen. Der Vorteil dieser Lösung besteht darin, dass kein externer Dienst abgefragt werden muss:

defmod Fritzbox FRITZBOX 192.168.123.123
attr Fritzbox INTERVAL 300
attr Fritzbox boxUser <dein Fritzbox User>
attr Fritzbox nonblockingTimeOut 100

Hierbei sind die Attribute wie die IP Adresse und Nutzername auf der Fritzbox anzupassen.

Die IPv4 und IPv6 der Fritzbox, als auch das IPv6 Prefix des lokalen Netzes sind als Readings direkt abfragbar:

box_ipv4_Extern
box_ipv6_Extern
box_ipv6_Prefix

Spezielle Abfrage der Fritzbox für Sonderfälle

In einigen Fällen stellt das Fritzbox Device nicht die passenden Readings bereit (zum Beispiel bei einer FB 6660 cable). Da in solchen Fällen CGNAT/DS-Lite eine IPv4 Abfrage vom Internet aus auf FHEM verhindert ist nur die öffentlich erreichbare IPv6 Adresse von Interesse (=GUA).


Es steht zur Zeit nur ein BASH Skript bereit (Quelle):

#!/bin/bash

FRITZ_USER="<USER>"
FRITZ_PASS="<PASS>"
FRITZ_HOSTNAME="<HOST>"

FRITZ_IPV6_GUA=$(curl -s --max-time 10 \
    --anyauth --user "${FRITZ_USER}:${FRITZ_PASS}" \
    http://${FRITZ_HOSTNAME}:49000/upnp/control/wanipconnection1 \
    -H "Content-Type: text/xml; charset="utf-8"" \
    -H "SoapAction:urn:dslforum-org:service:WANIPConnection:1#GetExternalIPAddress" \
    -d "<?xml version='1.0' encoding='utf-8'?> <s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'> <s:Body> <u:GetExternalIPAddress xmlns:u='urn:dslforum-org:service:WANIPConnection:1'></u:GetExternalIPAddress> </s:Body> </s:Envelope>" | egrep -o "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?")
if [ -z "$FRITZ_IPV6_GUA" ]; then
    echo "Error! Can't get IPv6 GUA from FRITZ!Box"
    exit 0
else
    echo "FRITZ!Box IPv6 GUA is: $FRITZ_IPV6_GUA"
fi

STUN Server nutzen

Alternativ kann ein STUN-Server zur Ermittlung der externen IP genutzt werden. Beispiel-Snippet (Perl):

sub myip {
  use STUN::Client;
  my $stun_client = STUN::Client->new;
  $stun_client->stun_server('stun.ekiga.net');
  my (undef, $result) = $stun_client->get;
  return $result->{'attributes'}->{'0001'}->{'address'};
}

Hinweis: Das Perl-Modul STUN::Client ist ggf. nicht in jeder Distribution verfügbar und muss über CPAN installiert werden.

Weitere Details und Diskussion: https://forum.fhem.de/index.php?topic=141872.msg1343225#msg1343225

IPs des FHEM Servers ermitteln (ohne Link-Local, Docker, etc)

Sofern der FHEM Server bereits eine öffentliche IP hat, kann man diese von den lokalen Netzwerkinterfaces abfragen. Mit wenigen Abhängigkeiten geht dies unter typischen Linux-Distributionen wie Debian Buster, Bullseye, Bookworm oder aktueller mit:

define LocalIPs at +*00:01:00 {
	my $hash = $defs{$SELF};
	my (@ipv4, @ipv6);
	
	#Abfragen der IP Adressen mittels CLI:
	my $json = qx(ip -j addr show scope global);
	my $data = decode_json($json);
    
	for my $iface (@$data) {
		for my $addr (@{$iface->{addr_info} || []}) {
			next unless $addr->{local};
			if ($addr->{family} eq 'inet') {
				push @ipv4, $addr->{local};
			} elsif ($addr->{family} eq 'inet6') {
				push @ipv6, $addr->{local};
			}
		}
	}
	
	readingsBeginUpdate($hash);
	readingsBulkUpdate($hash, "allIPv4", join(',', @ipv4));
	readingsBulkUpdate($hash, "allIPv6", join(',', @ipv6));
	readingsEndUpdate($hash, 1);
}
attr LocalIPs alignTime 00:00:00
attr LocalIPs event-on-change-reading .*
attr LocalIPs stateFormat IPv4: allIPv4<br />IPv6: allIPv6