다음을 통해 공유


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 함수는 이제 사용되지 않는 GetTeredoPort 또는 NotifyTeredoPortChange 함수 대신 구현 되어야 합니다.

  • 방화벽은 UPnP 검색 트래픽이 흐르고 연결 속도가 향상될 수 있으므로 시스템이 로컬 서브넷의 UDP 포트 1900에 UDP/IPv4 패킷을 보내고 받을 수 있도록 허용합니다.

    참고

    이 조건이 충족되지 않으면 특정 NAT 형식 간의 통신과 관련된 호환성 문제가 발생할 수 있는 시나리오가 도입됩니다. 특히 대칭 NAT와 제한된 NAT 사이. 대칭 NAT는 핫스팟에서 인기가 있고 제한된 NAT는 가정에서 인기가 있지만, 둘 사이의 통신은 제한된 NAT의 측면에 오류가 발생할 가능성이 있습니다.

     

  • 들어오고 나가는 ICMPv6 "Echo Request" 및 "Echo Reply" 예외를 사용하도록 설정해야 합니다. 이러한 예외는 Teredo 클라이언트가 Teredo 호스트별 릴레이 역할을 할 수 있도록 하는 데 필요합니다. Teredo 호스트별 릴레이는 추가 네이티브 IPv6 주소 또는 Teredo 주소와 함께 제공되는 6to4 주소로 식별할 수 있습니다.

클라이언트 방화벽은 RFC 4443당 다음 ICMPv6 오류 메시지 및 검색 기능을 지원해야 합니다.

코드 Description
135/136 ICMPV6 인접 요청 및 광고
133/134 라우터 요청 및 광고
128/129 ICMPV6 Echo Request and Reply
1 대상에 연결할 수 없음
2 패킷이 너무 큼
3 초과된 시간
4 잘못된 매개 변수

 

이러한 메시지를 구체적으로 허용할 수 없는 경우 방화벽에서 모든 ICMPv6 메시지의 예외를 사용하도록 설정해야 합니다. 또한 호스트 방화벽은 코드 135/136 또는 133/134로 분류된 패킷이 스택이 아닌 사용자 모드 서비스 iphlpsvc 에서 발생하거나 대상으로 지정되었음을 알 수 있습니다. 호스트 방화벽에서 이러한 패킷을 삭제해서는 안 됩니다. Teredo 서비스는 주로 '사용자 모드' IP 도우미 서비스 내에서 구현됩니다.

INetFwPolicy2 Windows 방화벽 API를 사용하여 Edge Traversal 플래그가 설정된 모든 규칙을 열거하면 원치 않는 트래픽을 수신 대기하려는 모든 애플리케이션이 방화벽 예외에 대해 열거됩니다. Edge Traversal 옵션 사용에 대한 구체적인 정보는 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;
}