Erforderliche Firewall-Ausnahmen für Teredo
Damit eine Anwendung Teredo-Datenverkehr empfängt, muss die Anwendung IPv6-Datenverkehr in der Hostfirewall empfangen dürfen, und die Anwendung muss die Socketoption IPV6_PROTECTION_LEVEL auf "PROTECTION_LEVEL_UNRESTRICTED" festlegen. Um diese Art von Szenario zu aktivieren, müssen die in diesem Dokument beschriebenen Firewall-Ausnahmen implementiert werden.
Die folgenden Firewallkonfigurationen sind erforderlich, um eine reibungslose Zusammenarbeit zwischen einer Firewall und Teredo sicherzustellen:
Die Clientfirewall muss die Auflösung von teredo.ipv6.microsoft.com zulassen.
UDP-Port 3544 muss geöffnet sein, um sicherzustellen, dass Teredo-Clients erfolgreich mit dem Teredo-Server kommunizieren können.
Die Firewall muss dynamische UDP-Ports abrufen, die vom Teredo-Dienst auf dem lokalen Computer verwendet werden, indem die funktion FwpmSystemPortsGet0 aufgerufen wird; relevante Ports sind vom Typ FWPM_SYSTEM_PORT_TEREDO. Die FwpmSystemPortsGet0--Funktion sollte anstelle der jetzt veralteten GetTeredoPort-- oder NotifyTeredoPortChange--Funktionen implementiert werden.
Die Firewall ermöglicht es dem System, UDP/IPv4-Pakete an UDP-Port 1900 im lokalen Subnetz zu senden und zu empfangen, da dadurch UPnP-Ermittlungsdatenverkehr fließen kann und das Potenzial hat, die Verbindungsraten zu verbessern.
Anmerkung
Wenn diese Bedingung nicht erfüllt ist, können Szenarien Kompatibilitätsprobleme auftreten, die die Kommunikation zwischen bestimmten NAT-Typen betreffen; speziell zwischen symmetrischen NATs und eingeschränkten NATs. Während symmetrische NATs in Hotspots beliebt sind und eingeschränkte NATs in Häusern beliebt sind, hat die Kommunikation zwischen den beiden das Potenzial, auf der Seite der eingeschränkten NAT zu verfehlern.
Die Ausnahmen für eingehende und ausgehende ICMPv6 "Echo Request" und "Echo Reply" müssen aktiviert sein. Diese Ausnahmen sind erforderlich, um sicherzustellen, dass ein Teredo-Client als hostspezifisches Relay fungieren kann. Ein hostspezifisches Teredo-Relay kann durch die zusätzliche systemeigene IPv6-Adresse oder eine 6to4-Adresse identifiziert werden, die mit der Teredo-Adresse angegeben ist.
Clientfirewalls müssen die folgenden ICMPv6-Fehlermeldungen und Ermittlungsfunktionen pro RFC 4443 unterstützen:
Code | Beschreibung |
---|---|
135/136 | ICMPV6 Nachbarwerbung und Werbung |
133/134 | Router Solicitation and Advertisement |
128/129 | ICMPV6 Echo-Anforderung und -Antwort |
1 | Ziel nicht erreichbar |
2 | Paket zu groß |
3 | Überschrittene Zeit |
4 | Ungültiger Parameter |
Wenn diese Nachrichten nicht ausdrücklich zulässig sind, sollte die Ausnahme aller ICMPv6-Nachrichten in der Firewall aktiviert werden. Darüber hinaus kann die Hostfirewall feststellen, dass die pakete, die durch Codes 135/136 oder 133/134 klassifiziert wurden, von dem Benutzermodusdienst iphlpsvc und nicht von dem Stapel stammen. Diese Pakete dürfen nicht von der Hostfirewall abgelegt werden. Der Teredo-Dienst wird in erster Linie innerhalb des IP-Hilfsdiensts "Benutzermodus" implementiert.
Verwenden der INetFwPolicy2 Windows-Firewall-API zum Aufzählen aller Regeln mit dem Edge Traversal-Flagsatz, werden alle Anwendungen, die auf unerwünschten Datenverkehr lauschen möchten, für die Firewallausnahme aufgelistet. Spezifische Informationen zur Verwendung der Option "Edge-Traversal" sind in Empfangen nicht angeforderter Datenverkehr über Teredodetailliert beschrieben.
Rückrufe sind nicht mit dem folgenden Beispielaufzählungscode verknüpft. Es wird dringend empfohlen, dass Firewalls von Drittanbietern die Enumeration regelmäßig ausführen oder wenn die Firewall eine neue Anwendung erkennt, die versucht, die Firewall durchzugehen.
#include <windows.h>
#include <objbase.h>
#include <stdio.h>
#include <atlcomcli.h>
#include <strsafe.h>
#include <netfw.h>
#define NET_FW_IP_PROTOCOL_TCP_NAME L"TCP"
#define NET_FW_IP_PROTOCOL_UDP_NAME L"UDP"
#define NET_FW_RULE_DIR_IN_NAME L"In"
#define NET_FW_RULE_DIR_OUT_NAME L"Out"
#define NET_FW_RULE_ACTION_BLOCK_NAME L"Block"
#define NET_FW_RULE_ACTION_ALLOW_NAME L"Allow"
#define NET_FW_RULE_ENABLE_IN_NAME L"TRUE"
#define NET_FW_RULE_DISABLE_IN_NAME L"FALSE"
#import "netfw.tlb"
void DumpFWRulesInCollection(long Allprofiletypes, NetFwPublicTypeLib::INetFwRulePtr FwRule)
{
variant_t InterfaceArray;
variant_t InterfaceString;
if(FwRule->Profiles == Allprofiletypes)
{
wprintf(L"---------------------------------------------\n");
wprintf(L"Name: %s\n", (BSTR)FwRule->Name);
wprintf(L"Description: %s\n", (BSTR)FwRule->Description);
wprintf(L"Application Name: %s\n", (BSTR)FwRule->ApplicationName);
wprintf(L"Service Name: %s\n", (BSTR)FwRule->serviceName);
switch(FwRule->Protocol)
{
case NET_FW_IP_PROTOCOL_TCP: wprintf(L"IP Protocol: %s\n", NET_FW_IP_PROTOCOL_TCP_NAME);
break;
case NET_FW_IP_PROTOCOL_UDP: wprintf(L"IP Protocol: %s\n", NET_FW_IP_PROTOCOL_UDP_NAME);
break;
default:
break;
}
if(FwRule->Protocol != NET_FW_IP_VERSION_V4 && FwRule->Protocol != NET_FW_IP_VERSION_V6)
{
wprintf(L"Local Ports: %s\n", (BSTR)FwRule->LocalPorts);
wprintf(L"Remote Ports: %s\n", (BSTR)FwRule->RemotePorts);
}
wprintf(L"LocalAddresses: %s\n", (BSTR)FwRule->LocalAddresses);
wprintf(L"RemoteAddresses: %s\n", (BSTR)FwRule->RemoteAddresses);
wprintf(L"Profile: %d\n", Allprofiletypes);
if(FwRule->Protocol == NET_FW_IP_VERSION_V4 || FwRule->Protocol == NET_FW_IP_VERSION_V6)
{
wprintf(L"ICMP TypeCode: %s\n", (BSTR)FwRule->IcmpTypesAndCodes);
}
switch(FwRule->Direction)
{
case NET_FW_RULE_DIR_IN:
wprintf(L"Direction: %s\n", NET_FW_RULE_DIR_IN_NAME);
break;
case NET_FW_RULE_DIR_OUT:
wprintf(L"Direction: %s\n", NET_FW_RULE_DIR_OUT_NAME);
break;
default:
break;
}
switch(FwRule->Action)
{
case NET_FW_ACTION_BLOCK:
wprintf(L"Action: %s\n", NET_FW_RULE_ACTION_BLOCK_NAME);
break;
case NET_FW_ACTION_ALLOW:
wprintf(L"Action: %s\n", NET_FW_RULE_ACTION_ALLOW_NAME);
break;
default:
break;
}
InterfaceArray = FwRule->Interfaces;
if(InterfaceArray.vt != VT_EMPTY)
{
SAFEARRAY *pSa = NULL;
long index = 0;
pSa = InterfaceArray.parray;
for(long index= pSa->rgsabound->lLbound; index < (long)pSa->rgsabound->cElements; index++)
{
SafeArrayGetElement(pSa, &index, &InterfaceString);
wprintf(L"Interfaces: %s\n", (BSTR)InterfaceString.bstrVal);
}
}
wprintf(L"Interface Types: %s\n", (BSTR)FwRule->InterfaceTypes);
if(FwRule->Enabled)
{
wprintf(L"Enabled: %s\n", NET_FW_RULE_ENABLE_IN_NAME);
}
else
{
wprintf(L"Enabled: %s\n", NET_FW_RULE_DISABLE_IN_NAME);
}
wprintf(L"Grouping: %s\n", (BSTR)FwRule->Grouping);
wprintf(L"Edge: %s\n", (BSTR)FwRule->EdgeTraversal);
}
}
int __cdecl main()
{
HRESULT hr;
BOOL fComInitialized = FALSE;
ULONG cFetched = 0;
CComVariant var;
long Allprofiletypes = 0;
try
{
IUnknownPtr pEnumerator = NULL;
IEnumVARIANT* pVariant = NULL;
NetFwPublicTypeLib::INetFwPolicy2Ptr sipFwPolicy2;
//
// Initialize the COM library on the current thread.
//
hr = CoInitialize(NULL);
if (FAILED(hr))
{
_com_issue_error(hr);
}
fComInitialized = TRUE;
hr = sipFwPolicy2.CreateInstance("HNetCfg.FwPolicy2");
if (FAILED(hr))
{
_com_issue_error(hr);
}
Allprofiletypes = NET_FW_PROFILE2_ALL; // 0x7FFFFFFF
printf("The number of rules in the Windows Firewall are %d\n", sipFwPolicy2->Rules->Count);
pEnumerator = sipFwPolicy2->Rules->Get_NewEnum();
if(pEnumerator)
{
hr = pEnumerator->QueryInterface(__uuidof(IEnumVARIANT), (void **) &pVariant);
}
while(SUCCEEDED(hr) && hr != S_FALSE)
{
NetFwPublicTypeLib::INetFwRulePtr sipFwRule;
var.Clear();
hr = pVariant->Next(1, &var, &cFetched);
if (S_FALSE != hr)
{
if (SUCCEEDED(hr))
{
hr = var.ChangeType(VT_DISPATCH);
}
if (SUCCEEDED(hr))
{
hr = (V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&sipFwRule));
}
if (SUCCEEDED(hr))
{
DumpFWRulesInCollection(Allprofiletypes, sipFwRule);
}
}
}
}
catch(_com_error& e)
{
printf ("Error. HRESULT message is: %s (0x%08lx)\n", e.ErrorMessage(), e.Error());
if (e.ErrorInfo())
{
printf ("Description: %s\n", (char *)e.Description());
}
}
if (fComInitialized)
{
CoUninitialize();
}
return 0;
}