Desktop App/C#.Net

[C# .NET] Windows 방화벽 등록하기

Jade Choe 2022. 3. 3. 23:16
SMALL

TCP 통신 기능이 있는 닷넷 프레임워크 앱들은 실행하면 아래와 같은 창이 뜨고,

허용 시 윈도우 방화벽에 자동으로 등록이 된다.

 

 

이 때 네트워크 프로필과 다른 옵션을 선택하거나 엑세스를 허용하지 않은 경우,

또는 무언가 알 수 없는 오류로 위 창조차 보이지 않고 방화벽에 등록이 되지 않는 경우가 생긴다.

 

해당 문제로 고객사측 앱 사용에 문제가 있어 방화벽에 앱을 자동으로 등록해줄 수 있도록 해주었다.

 

테스트하기 위해 간단한 프로젝트를 생성했다.

 

참조 우클릭 -> 참조 추가

 

COM 항목에서 NetFw라고 검색하면 위와 같이 NetFwTypeLib 라이브러리가 나온다.

체크하여 참조해준다.

 

테스트만 하고 끝낼 것이 아니라 배포용 앱에도 추가해야 하기 때문에 따로 클래스를 만들어 주었다.

using System;
using System.Linq;
using NetFwTypeLib;

namespace FirewallTest
{
    public static class Firewall
    {
        public enum Protocol
        {
            TCPUDP = 0x100,
            TCP = 6,
            UDP = 0x11
        }
        public enum Direction
        {
            INBOUND = 1,
            OUTBOUND = 2,
            MAX = 3
        }

        public enum Action
        {
            BLOCK = 0,
            ALLOW = 1,
            MAX = 2
        }

        private static INetFwPolicy2 policy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));

        public static bool Find(string name, string path)
        {
            return policy.Rules.Cast<INetFwRule>().Any(rule => rule.Name == name && rule.ApplicationName == path);
        }
        public static bool Find(string name, Protocol protocol)
        {
            return policy.Rules.Cast<INetFwRule>().Any(r => r.Name == name && r.Protocol == (int)protocol);
        }

        /// <summary>
        /// Add Firewall Rule
        /// </summary>
        /// <param name="name">Rule Name</param>
        /// <param name="path">Program Full Path</param>
        /// <param name="direction">Direction</param>
        /// <param name="action">Action</param>
        /// <returns>If added, will returns true. Elif Removed, will returns false.</returns>
        public static bool Add(string name, string path, Direction direction, Action action)
        {
            if (Find(name, path)) return true;

            INetFwRule rule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));

            rule.Name = name;
            rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_ANY;
            rule.Direction = (NET_FW_RULE_DIRECTION_)direction;
            rule.Enabled = true;
            rule.Action = (NET_FW_ACTION_)action;
            
            policy.Rules.Add(rule);

            return Find(name, path);
        }
        /// <summary>
        /// Add Firewall Rule
        /// </summary>
        /// <param name="name">Rule Name</param>
        /// <param name="protocol">Protocol Type</param>
        /// <param name="direction">Direction</param>
        /// <param name="action">Action</param>
        /// <returns>If added, will returns true. Elif Removed, will returns false.</returns>
        public static bool Add(string name, Protocol protocol, Direction direction, Action action)
        {
            if (Find(name, protocol)) return true;

            INetFwRule rule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));

            rule.Name = name;
            rule.Protocol = (int)protocol;
            rule.Direction = (NET_FW_RULE_DIRECTION_)direction;
            rule.Enabled = true;
            rule.Action = (NET_FW_ACTION_)action;

            policy.Rules.Add(rule);

            return Find(name, protocol);
        }

        /// <summary>
        /// Remove Firewall Rule
        /// </summary>
        /// <param name="name">Rule Name</param>
        /// <param name="protocol">Protocol Type</param>
        /// <returns>If Removed or Not exist, will returns true. Elif It didn't Removed, will returns false.</returns>
        public static bool Remove(string name, Protocol protocol)
        {
            if (!Find(name, protocol)) return true;

            INetFwRule rule = policy.Rules.Cast<INetFwRule>().FirstOrDefault(r => r.Name == name && r.Protocol == (int)protocol);

            if (rule != null) policy.Rules.Remove(name);

            return !Find(name, protocol);
        }
    }
}

 

 

테스트해보기 위해 아래 코드를 버튼에 넣고 시험해 보았다.

Firewall.Add(Application.ProductName, Application.ExecutablePath, Firewall.Direction.INBOUND, Firewall.Action.ALLOW);
Firewall.Add(Application.ProductName + "2", Firewall.Protocol.TCP, Firewall.Direction.INBOUND, Firewall.Action.ALLOW);

Firewall.Remove(Application.ProductName, Firewall.Protocol.TCPUDP);

 

 

적용 전

 

적용 후

 

 

삭제 후

 

 

특정 프로토콜만 허용

 

 

특정 포트만 허용하는 메서드도 넣으려고 했으나, 무슨 이유에서인지 ArgumentException이 뜨며 적용되지 않는다.

 

 

BIG