Udostępnij przez


Wymagane wyjątki zapory dla teredo

Aby aplikacja odbierała ruch Teredo, aplikacja musi mieć zezwolenie na odbieranie ruchu IPv6 w zaporze hosta, a aplikacja musi ustawić opcję gniazda IPV6_PROTECTION_LEVEL na wartość "PROTECTION_LEVEL_UNRESTRICTED". Aby włączyć ten typ scenariusza, należy zaimplementować wyjątki zapory opisane w tym dokumencie.

Następujące konfiguracje zapory są wymagane w celu zapewnienia bezproblemowej współpracy między zaporą a teredo:

  • Zapora klienta musi zezwalać na rozpoznawanie teredo.ipv6.microsoft.com.

  • Port UDP 3544 musi być otwarty, aby upewnić się, że klienci Teredo mogą pomyślnie komunikować się z serwerem Teredo.

  • Zapora musi pobrać dynamiczne porty UDP używane przez usługę Teredo na komputerze lokalnym przez wywołanie funkcji FwpmSystemPortsGet0; odpowiednie porty są typu FWPM_SYSTEM_PORT_TEREDO. Funkcja FwpmSystemPortsGet0 powinna zostać zaimplementowana zamiast przestarzałych funkcji GetTeredoPort lub NotifyTeredoPortChange.

  • Zapora zezwala systemowi na wysyłanie i odbieranie pakietów UDP/IPv4 do portu UDP 1900 w podsieci lokalnej, ponieważ umożliwia to przepływ ruchu odnajdywania protokołu UPnP i ma potencjał poprawy szybkości łączności.

    Nuta

    Jeśli ten warunek nie zostanie spełniony, zostanie wprowadzony potencjał scenariuszy napotkania problemów ze zgodnością związanych z komunikacją między określonymi typami translatora adresów sieciowych; w szczególności między symetrycznymi sieciami dostępu do sieci i ograniczonymi sieciami dostępu do sieci. Podczas gdy symetryczne sieci nats są popularne w hotspotach i ograniczone SIECI są popularne w domach, komunikacja między nimi ma potencjał do uszkodzenia po stronie ograniczonego translatora adresów sieciowych.

     

  • Należy włączyć wyjątki przychodzące i wychodzące ICMPv6 "Echo Request" i "Echo Reply". Te wyjątki są niezbędne do zapewnienia, że klient Teredo może działać jako przekaźnik specyficzny dla hosta Teredo. Przekaźnik specyficzny dla hosta Teredo można zidentyfikować za pomocą dodatkowego natywnego adresu IPv6 lub adresu 6to4 dostarczonego z adresem Teredo.

Zapory klienta muszą obsługiwać następujące komunikaty o błędach ICMPv6 i funkcje odnajdywania na RFC 4443:

Kod Opis
135/136 ICMPV6 Żądanie sąsiada i anonsowanie
133/134 Żądanie i anonsowanie routera
128/129 Żądanie echa i odpowiedź ICMPV6
1 Miejsce docelowe nie jest osiągalne
2 Za duży pakiet
3 Przekroczono czas
4 Nieprawidłowy parametr

 

Jeśli te komunikaty nie mogą być w szczególności dozwolone, należy włączyć wykluczenie wszystkich komunikatów ICMPv6 w zaporze. Ponadto zapora hosta może zauważyć, że pakiety sklasyfikowane przez kody 135/136 lub 133/134 pochodzą z usługi trybu użytkownika iphlpsvc, a nie ze stosu. Te pakiety nie mogą być porzucane przez zaporę hosta. Usługa Teredo jest implementowana głównie w usłudze pomocnika IP trybu użytkownika.

Przy użyciu interfejsu API zapory systemu Windows INetFwPolicy2 wyliczanie wszystkich reguł z ustawioną flagą Przechodzenie krawędzi wszystkie aplikacje, które chcą nasłuchiwać niepożądanego ruchu, są wyliczane dla wyjątku zapory. Szczegółowe informacje dotyczące korzystania z opcji przechodzenia krawędzi zostały szczegółowo opisane w Odbieranie niepożądanego ruchu przezTeredo.

Wywołania zwrotne nie są skojarzone z następującym przykładowym kodem wyliczenia; Zdecydowanie zaleca się, aby zapory innych firm okresowo wykonywać wyliczanie lub gdy zapora wykryje nową aplikację próbującą przejść przez zaporę.

#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;
}