共用方式為


Teredo 的必要防火牆例外狀況

若要讓應用程式接收 Teredo 流量,應用程式必須允許在主機防火牆中接收 IPv6 流量,而且應用程式必須將通訊端選項 IPV6_PROTECTION_LEVEL 設定為 'PROTECTION_LEVEL_UNRESTRICTED'。 若要啟用這種類型的案例,必須實作本檔中詳述的防火牆例外狀況。

需要下列防火牆設定,以確保防火牆與 Teredo 之間的順暢互通:

  • 用戶端防火牆必須允許解析 teredo.ipv6.microsoft.com。

  • UDP 埠 3544 必須開啟,以確保 Teredo 用戶端可以成功與 Teredo 伺服器通訊。

  • 防火牆必須藉由呼叫 FwpmSystemPortsGet0 函式,在本機電腦上擷取 Teredo 服務所使用的動態 UDP 埠;相關的埠類型為 FWPM_SYSTEM_PORT_TEREDO。 FwpmSystemPortsGet0函式應該實作,以取代現在已被取代的GetTeredoPortNotifyTeredoPortChange函式。

  • 防火牆允許系統在本機子網上將 UDP/IPv4 封包傳送和接收到 UDP 埠 1900,因為這樣可讓 UPnP 探索流量流動,並可能改善連線速率。

    注意

    如果不符合此條件,就會引進涉及特定 NAT 類型之間通訊的案例可能發生相容性問題;特別是對稱 NAT 與受限制的 NAT 之間。 雖然對稱 NAT 在熱點中很受歡迎,而受限制的 NAT 在家庭中很受歡迎,但兩者之間的通訊可能會造成限制 NAT 的側邊發生錯誤。

     

  • 必須啟用傳入和傳出 ICMPv6 「Echo Request」 和 「Echo Reply」 例外狀況。 這些例外狀況是確保 Teredo 用戶端可以做為 Teredo 主機特定轉送的必要條件。 Teredo 主機特定轉寄可由其他原生 IPv6 位址或 Teredo 位址提供的 6to4 位址來識別。

用戶端防火牆必須支援下列 ICMPv6 錯誤訊息和每個 RFC 4443 的探索函式:

程式碼 描述
135/136 ICMPV6 芳鄰要求和廣告
133/134 路由器要求和公告
128/129 ICMPV6 回應要求和回復
1 目的地無法連線
2 封包太大
3 超過時間
4 不正確參數

 

如果無法特別允許這些訊息,則應在防火牆上啟用所有 ICMPv6 訊息的豁免。 此外,主機防火牆可能會注意到由代碼 135/136 或 133/134 所分類的封包源自使用者模式服務 iphlpsvc ,而不是來自堆疊。 主機防火牆不得卸載這些封包。 Teredo 服務主要是在「使用者模式」IP 協助程式服務內實作。

使用 INetFwPolicy2 Windows 防火牆 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;
}