프로그램적으로 윈도우 방화벽 설정하기

.

오랜만에~ 정말 오래간만에 포스팅을 합니다. :)

그동안 회사를 이직하고, 결혼도 하고 하느라 정신이 없다는 핑계로 블로그 운영에 많이 소홀했네요.


재밌는 일도 많고(IT 적으로), 다양한것들을 해 보았는데.

블로깅할 시간이 없었어요~ ㅎ.



모쪼록, 방화벽 관련해서 포스팅을 하려고 합니다.

이전에 한번 netsh 을 통한 방화벽 설정 글을 올린적이 있었는데

(http://crystalcube.co.kr/entry/%EC%9C%88%EB%8F%84%EC%9A%B0-%EB%B0%A9%ED%99%94%EB%B2%BD-%ED%95%B4%EC%A0%9C%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95#recentTrackback)


이번엔 코드레벨에서 COM 개체를 이용하여 처리하는 방법입니다.

코드는 .NET 이고, XP 이후 버젼부터 동작 가능합니다.



    [방화벽 설정]


public static class FirewallAPI
{
    private static INetFwPolicy2 _firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
        
    //public enum FirewallAction
    //{
    //    Block = 0,
    //    Allow = 1,
    //    Max = 2
    //}


    //public enum FirewallDirection
    //{
    //    In = 1,
    //    Out = 2,
    //    Max = 3
    //}

    public enum Protocol
    {
        Tcp = 6,
        Udp = 0x11,
        Any = 0x100
    }



    public static bool AddInboudRule(string name, string programFullPath) {
        if (IsInboundRuleExist(name, programFullPath) == true) { return true; }

        INetFwRule newRule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
        newRule.Name = name;
        newRule.ApplicationName = programFullPath;
        newRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_ANY;
        newRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
        newRule.Enabled = true;
        newRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;

        _firewallPolicy.Rules.Add(newRule);

        return IsInboundRuleExist(name, programFullPath);
    }



    private static bool IsInboundRuleExist(string name, string programFullPath)
    {
        return _firewallPolicy.Rules.Cast<INetFwRule>().Any(rule => rule.Name == name && rule.ApplicationName == programFullPath);
    }



    private static bool IsInboundRuleExist(string name, Protocol protocol, int port)
    {
        return _firewallPolicy.Rules.Cast<INetFwRule>().Any(r => r.Name == name && r.Protocol == (int)protocol && r.LocalPorts == port.ToString());
    }

    private static bool IsInboundRuleExist(string name, Protocol protocol) {
        return _firewallPolicy.Rules.Cast<INetFwRule>().Any(r => r.Name == name && r.Protocol == (int)protocol);
    }



    public static bool AddInboudRule(string name, Protocol protocol, int port)
    {
        if (IsInboundRuleExist(name, protocol, port) == true) { return true; }

        INetFwRule newRule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
        newRule.Name = name;
        newRule.Protocol = (int) protocol;
        newRule.LocalPorts = port.ToString();
        newRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
        newRule.Enabled = true;
        newRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;

        _firewallPolicy.Rules.Add(newRule);

        return IsInboundRuleExist(name, protocol, port);
    }



    public static bool RemoveInboundRule(string name, Protocol protocol, int port)
    {
        if (IsInboundRuleExist(name, protocol, port) == false) { return true; }

        INetFwRule rule = _firewallPolicy.Rules.Cast<INetFwRule>().FirstOrDefault(r => r.Name == name && r.Protocol == (int) protocol && r.LocalPorts.Contains(port.ToString()));
        if (rule != null) { _firewallPolicy.Rules.Remove(name); }
            
        return IsInboundRuleExist(name, protocol, port) == false;
    }


    public static bool RemoveInboundRule(string name, Protocol protocol) {
        if (IsInboundRuleExist(name, protocol) == false) { return true; }

        INetFwRule rule = _firewallPolicy.Rules.Cast<INetFwRule>().FirstOrDefault(r => r.Name == name && r.Protocol == (int)protocol);
        if (rule != null) { _firewallPolicy.Rules.Remove(name); }

        return IsInboundRuleExist(name, protocol) == false;
    }
}





먼저 코드를 작성하려면, 언급했듯이 COM 인터페이스를 추가해 주어야 합니다.

어셈블리 파일명은 NetFwTypeLib 이고, 프로젝트 참조추가 해 주어야 합니다.



당연히 COM 카테고리에서 찾아봐야 겠지요 ^-^


그리고 코드 상단에서 using 해 주어야 합니다.



    [NetFwTypeLib]


using NetFwTypeLib;





샘플코드에서는 인바운드(Inbound) 규칙에 대해서 설정하는 것을 다루었습니다.

Outbound 도 어렵지 않게 하실 수 있을거라고 생각합니다.


'Inbound / Outbound', 'TCP,UDP,...' 등의 값들은 모두 NetFwTypeLib 안에 enum 으로 정의되어 있으니 참고하시면 됩니다.

코드상에서 제가 enum 으로 다시 정의한 것들은, 샘플코드를 쓰는 쪽에서 NetFwTypeLib 를 별도로 Import 하지 않아도 되게 하려고.. 한 것입니다.


모쪼록, 많은 도움 되셨길 바랍니다. :)

'Microsoft > C#' 카테고리의 다른 글

#warning, #error, #line 지시자  (0) 2014.05.08
인증서(certification) 만들기  (1) 2014.04.09
윈도우즈 방화벽 규칙 추가/설정/삭제하기  (3) 2014.03.27
키보드 마우스 글로벌 후킹  (1) 2012.06.15
MessageQueue 구현하기  (2) 2011.05.08
JSON 과 AJAX 그리고 C#  (0) 2011.04.25
  • Anonymous 2014.04.08 21:58

    안녕하세요
    대학교 재학중인 학생입니다.

    현재 C언어 교육 프로그램 프로젝트 진행중인데
    컴파일 구현방법을 읽어보았으나. 현재 만들어진 프로그램이 필요하게되서 글남겨봅니다.

    MFC 에서 Dialog 상자 하나 생성후에

    에디트 박스 하나, 텍스트 박스 하나, 버튼하나를 생성합니다.

    그 후에 에디트박스에서 코딩후 버튼을 누르게되면. 텍스트박스에 결과가 뜰 수 있는 방법을 구현하고
    싶습니다.

    만약 오류가 뜨게되면. 텍스트 박스에 결과대신 오류가 뜨도록 (그냥 완전한 비주얼 스투디오에 컴파일 식으로) 구현하고 싶습니다. (오류를 누르면 그 줄까지 커서가 위치하지 않아도 됩니다..)

    혹시 컴파일 소스좀 얻을수 있을까요..?
    wjd_wogns@nate.com 연락좀 주시기 바랍니다.!!

    • unD3R 2014.04.09 11:48 신고

      안녕하세요?
      만들고 싶으신게, C언어 컴파일러인지 아니면 비쥬얼스튜디오 같은 IDE 툴인지 정확히 모르겠네요.

      먼저 C언어 컴파일러를 직접 만들고 싶으신 거라면,,
      이는 매우 복잡하고 어렵습니다. 시간도 상당히 많이 소요됩니다.
      syntax 정의 하는데만도 몇달이 걸릴것으로 예상됩니다. 이후 어셈(or 기계어)으로 빌드하는 과정도 상당히 복잡하지요. 제 블로그에 컴파일러 관련 글을 올린게 있는데, 매우매우 심플한 언어를 정의하고 컴파일러를 만드는데도 복잡합니다.

      만약 MFC로 비쥬얼스튜디오의 컴파일러(devenv.exe)를 사용해서 IDE 를 만들고 싶으신 거라면, 이는 매우 간단합니다.
      작성된 코드를 devenv.exe 프로세스에게 넘겨주고, 결과값(STDOUT/STDERR)을 스트림에서 읽어서, 단순 출력만 해 주면 됩니다.
      실제 비쥬얼스튜디오도 이런 방식으로 구현되어 있습니다.
      exe 를 실행하고, 결과만 출력하는 방식이죠.

      도움이 되었는지 모르겠네요. 그럼 수고하세요!

  • 개발초보 2019.02.11 17:05

    안녕하세요?
    wcf관련해서 웹 서비스를 제공해주고있는데요..
    해당 ip주소의 포트를 열어주기 위해서 인바운드 규칙이 필요한데..

    tcp에 8080 규칙을 넣어주고싶을땐 어떻게하면 될까요?