アプリケーションが Teredo トラフィックを受信するには、アプリケーションがホスト ファイアウォールで IPv6 トラフィックを受信することを許可する必要があります。また、アプリケーションはソケット オプション IPV6_PROTECTION_LEVEL を "PROTECTION_LEVEL_UNRESTRICTED" に設定する必要があります。 この種のシナリオを有効にするには、このドキュメントで詳しく説明されているファイアウォール例外を実装する必要があります。
ファイアウォールと Teredo の間の円滑な相互運用を確保するには、次のファイアウォール構成が必要です。
クライアント ファイアウォールは、teredo.ipv6.microsoft.com の解決を許可する必要があります。
Teredo クライアントが Teredo サーバーと正常に通信できるようにするには、UDP ポート 3544 を開く必要があります。
ファイアウォールは、FwpmSystemPortsGet0 関数を呼び出すことによって、ローカル コンピューター上の Teredo サービスによって使用される動的 UDP ポートを取得する必要があります。関連するポートの種類はFWPM_SYSTEM_PORT_TEREDOです。 FwpmSystemPortsGet0 関数は、現在非推奨になった GetTeredoPort または NotifyTeredoPortChange関数代わりに実装する必要があります。
ファイアウォールにより、システムはローカル サブネット上の UDP ポート 1900 に UDP/IPv4 パケットを送受信できます。これにより、UPnP 検出トラフィックが流れ、接続速度が向上する可能性があります。
手記
この条件が満たされていない場合、特定の NAT 型間の通信に関連する互換性の問題が発生する可能性があります。特に、対称 NAT と制限付き NAT の間で行います。 対称 NAT はホットスポットで人気があり、制限付き NAT は家庭で人気ですが、2 つの間の通信は制限付き NAT の側で障害が発生する可能性があります。
受信および送信 ICMPv6 の "エコー要求" 例外と "エコー応答" 例外を有効にする必要があります。 これらの例外は、Teredo クライアントが Teredo ホスト固有のリレーとして機能できるようにするために必要です。 Teredo ホスト固有のリレーは、追加のネイティブ IPv6 アドレスまたは Teredo アドレスで指定された 6to4 アドレスで識別できます。
クライアント ファイアウォールは、RFC 4443 に従って、次の ICMPv6 エラー メッセージと検出機能をサポートする必要があります。
コード | 形容 |
---|---|
135/136 | ICMPV6 近隣の要請と広告 |
133/134 | ルーターの要請と広告 |
128/129 | ICMPV6 エコー要求と応答 |
1 | 宛先に到達できない |
2 | パケットが大きすぎます |
3 | 時間超過 |
4 | 無効なパラメーター |
これらのメッセージを明示的に許可できない場合は、すべての ICMPv6 メッセージの除外をファイアウォールで有効にする必要があります。 さらに、ホスト ファイアウォールは、コード 135/136 または 133/134 によって分類されたパケットが、スタックからではなく iphlpsvc ユーザー モード サービスから送信されるか、またはターゲットにされていることに気付く場合があります。 これらのパケットは、ホスト ファイアウォールによって破棄してはなりません。 Teredo サービスは、主に "ユーザー モード" IP ヘルパー サービス内に実装されます。
INetFwPolicy2 Windows Firewall API を使用して、Edge トラバーサル フラグが設定されているすべてのルールを列挙すると、要求されていないトラフィックをリッスンするすべてのアプリケーションがファイアウォール例外に対して列挙されます。 Edge トラバーサル オプションの使用に関する具体的な情報は、Teredo 経由の未承諾トラフィックの受信で詳しく説明されています。
コールバックは、次のサンプル列挙コードに関連付けされていません。サード パーティのファイアウォールが定期的に、またはファイアウォールを通過しようとしている新しいアプリケーションを検出するたびに、列挙を実行することを強くお勧めします。
#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;
}