2008-09-22 20 views
20

Tengo una aplicación que está instalada y actualizada a través de ClickOnce. La aplicación descarga archivos a través de FTP y, por lo tanto, debe agregarse como una excepción al firewall de Windows. Debido a la forma en que funciona ClickOnce, la ruta al EXE cambia con cada actualización, por lo que la excepción también necesita cambiar. ¿Cuál sería la mejor manera de tener los cambios realizados en el firewall para que sea invisible para el usuario final?Agregar una aplicación mediante programación a Firewall de Windows

(La aplicación está escrita en C#)

+0

estoy teniendo el mismo problema pero con otro software de seguridad (firewall no sólo Windows) – Jamiegs

Respuesta

9

Encontré este artículo, que tiene una clase de contenedor completa incluida para manipular el firewall de Windows. Adding an Application to the Exception list on the Windows Firewall

/// 

/// Allows basic access to the windows firewall API. 
/// This can be used to add an exception to the windows firewall 
/// exceptions list, so that our programs can continue to run merrily 
/// even when nasty windows firewall is running. 
/// 
/// Please note: It is not enforced here, but it might be a good idea 
/// to actually prompt the user before messing with their firewall settings, 
/// just as a matter of politeness. 
/// 

/// 
/// To allow the installers to authorize idiom products to work through 
/// the Windows Firewall. 
/// 
public class FirewallHelper 
{ 
    #region Variables 
    /// 

    /// Hooray! Singleton access. 
    /// 

    private static FirewallHelper instance = null; 

    /// 

    /// Interface to the firewall manager COM object 
    /// 

    private INetFwMgr fwMgr = null; 
    #endregion 
    #region Properties 
    /// 

    /// Singleton access to the firewallhelper object. 
    /// Threadsafe. 
    /// 

    public static FirewallHelper Instance 
    { 
     get 
     { 
      lock (typeof(FirewallHelper)) 
      { 
       if (instance == null) 
        instance = new FirewallHelper(); 
       return instance; 
      } 
     } 
    } 
    #endregion 
    #region Constructivat0r 
    /// 

    /// Private Constructor. If this fails, HasFirewall will return 
    /// false; 
    /// 

    private FirewallHelper() 
    { 
     // Get the type of HNetCfg.FwMgr, or null if an error occurred 
     Type fwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false); 

     // Assume failed. 
     fwMgr = null; 

     if (fwMgrType != null) 
     { 
      try 
      { 
       fwMgr = (INetFwMgr)Activator.CreateInstance(fwMgrType); 
      } 
      // In all other circumnstances, fwMgr is null. 
      catch (ArgumentException) { } 
      catch (NotSupportedException) { } 
      catch (System.Reflection.TargetInvocationException) { } 
      catch (MissingMethodException) { } 
      catch (MethodAccessException) { } 
      catch (MemberAccessException) { } 
      catch (InvalidComObjectException) { } 
      catch (COMException) { } 
      catch (TypeLoadException) { } 
     } 
    } 
    #endregion 
    #region Helper Methods 
    /// 

    /// Gets whether or not the firewall is installed on this computer. 
    /// 

    /// 
    public bool IsFirewallInstalled 
    { 
     get 
     { 
      if (fwMgr != null && 
        fwMgr.LocalPolicy != null && 
        fwMgr.LocalPolicy.CurrentProfile != null) 
       return true; 
      else 
       return false; 
     } 
    } 

    /// 

    /// Returns whether or not the firewall is enabled. 
    /// If the firewall is not installed, this returns false. 
    /// 

    public bool IsFirewallEnabled 
    { 
     get 
     { 
      if (IsFirewallInstalled && fwMgr.LocalPolicy.CurrentProfile.FirewallEnabled) 
       return true; 
      else 
       return false; 
     } 
    } 

    /// 

    /// Returns whether or not the firewall allows Application "Exceptions". 
    /// If the firewall is not installed, this returns false. 
    /// 

    /// 
    /// Added to allow access to this metho 
    /// 
    public bool AppAuthorizationsAllowed 
    { 
     get 
     { 
      if (IsFirewallInstalled && !fwMgr.LocalPolicy.CurrentProfile.ExceptionsNotAllowed) 
       return true; 
      else 
       return false; 
     } 
    } 

    /// 

    /// Adds an application to the list of authorized applications. 
    /// If the application is already authorized, does nothing. 
    /// 

    /// 
    ///   The full path to the application executable. This cannot 
    ///   be blank, and cannot be a relative path. 
    /// 
    /// 
    ///   This is the name of the application, purely for display 
    ///   puposes in the Microsoft Security Center. 
    /// 
    /// 
    ///   When applicationFullPath is null OR 
    ///   When appName is null. 
    /// 
    /// 
    ///   When applicationFullPath is blank OR 
    ///   When appName is blank OR 
    ///   applicationFullPath contains invalid path characters OR 
    ///   applicationFullPath is not an absolute path 
    /// 
    /// 
    ///   If the firewall is not installed OR 
    ///   If the firewall does not allow specific application 'exceptions' OR 
    ///   Due to an exception in COM this method could not create the 
    ///   necessary COM types 
    /// 
    /// 
    ///   If no file exists at the given applicationFullPath 
    /// 
    public void GrantAuthorization(string applicationFullPath, string appName) 
    { 
     #region Parameter checking 
     if (applicationFullPath == null) 
      throw new ArgumentNullException("applicationFullPath"); 
     if (appName == null) 
      throw new ArgumentNullException("appName"); 
     if (applicationFullPath.Trim().Length == 0) 
      throw new ArgumentException("applicationFullPath must not be blank"); 
     if (applicationFullPath.Trim().Length == 0) 
      throw new ArgumentException("appName must not be blank"); 
     if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0) 
      throw new ArgumentException("applicationFullPath must not contain invalid path characters"); 
     if (!Path.IsPathRooted(applicationFullPath)) 
      throw new ArgumentException("applicationFullPath is not an absolute path"); 
     if (!File.Exists(applicationFullPath)) 
      throw new FileNotFoundException("File does not exist", applicationFullPath); 
     // State checking 
     if (!IsFirewallInstalled) 
      throw new FirewallHelperException("Cannot grant authorization: Firewall is not installed."); 
     if (!AppAuthorizationsAllowed) 
      throw new FirewallHelperException("Application exemptions are not allowed."); 
     #endregion 

     if (!HasAuthorization(applicationFullPath)) 
     { 
      // Get the type of HNetCfg.FwMgr, or null if an error occurred 
      Type authAppType = Type.GetTypeFromProgID("HNetCfg.FwAuthorizedApplication", false); 

      // Assume failed. 
      INetFwAuthorizedApplication appInfo = null; 

      if (authAppType != null) 
      { 
       try 
       { 
        appInfo = (INetFwAuthorizedApplication)Activator.CreateInstance(authAppType); 
       } 
       // In all other circumnstances, appInfo is null. 
       catch (ArgumentException) { } 
       catch (NotSupportedException) { } 
       catch (System.Reflection.TargetInvocationException) { } 
       catch (MissingMethodException) { } 
       catch (MethodAccessException) { } 
       catch (MemberAccessException) { } 
       catch (InvalidComObjectException) { } 
       catch (COMException) { } 
       catch (TypeLoadException) { } 
      } 

      if (appInfo == null) 
       throw new FirewallHelperException("Could not grant authorization: can't create INetFwAuthorizedApplication instance."); 

      appInfo.Name = appName; 
      appInfo.ProcessImageFileName = applicationFullPath; 
      // ... 
      // Use defaults for other properties of the AuthorizedApplication COM object 

      // Authorize this application 
      fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(appInfo); 
     } 
     // otherwise it already has authorization so do nothing 
    } 
    /// 

    /// Removes an application to the list of authorized applications. 
    /// Note that the specified application must exist or a FileNotFound 
    /// exception will be thrown. 
    /// If the specified application exists but does not current have 
    /// authorization, this method will do nothing. 
    /// 

    /// 
    ///   The full path to the application executable. This cannot 
    ///   be blank, and cannot be a relative path. 
    /// 
    /// 
    ///   When applicationFullPath is null 
    /// 
    /// 
    ///   When applicationFullPath is blank OR 
    ///   applicationFullPath contains invalid path characters OR 
    ///   applicationFullPath is not an absolute path 
    /// 
    /// 
    ///   If the firewall is not installed. 
    /// 
    /// 
    ///   If the specified application does not exist. 
    /// 
    public void RemoveAuthorization(string applicationFullPath) 
    { 

     #region Parameter checking 
     if (applicationFullPath == null) 
      throw new ArgumentNullException("applicationFullPath"); 
     if (applicationFullPath.Trim().Length == 0) 
      throw new ArgumentException("applicationFullPath must not be blank"); 
     if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0) 
      throw new ArgumentException("applicationFullPath must not contain invalid path characters"); 
     if (!Path.IsPathRooted(applicationFullPath)) 
      throw new ArgumentException("applicationFullPath is not an absolute path"); 
     if (!File.Exists(applicationFullPath)) 
      throw new FileNotFoundException("File does not exist", applicationFullPath); 
     // State checking 
     if (!IsFirewallInstalled) 
      throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed."); 
     #endregion 

     if (HasAuthorization(applicationFullPath)) 
     { 
      // Remove Authorization for this application 
      fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Remove(applicationFullPath); 
     } 
     // otherwise it does not have authorization so do nothing 
    } 
    /// 

    /// Returns whether an application is in the list of authorized applications. 
    /// Note if the file does not exist, this throws a FileNotFound exception. 
    /// 

    /// 
    ///   The full path to the application executable. This cannot 
    ///   be blank, and cannot be a relative path. 
    /// 
    /// 
    ///   The full path to the application executable. This cannot 
    ///   be blank, and cannot be a relative path. 
    /// 
    /// 
    ///   When applicationFullPath is null 
    /// 
    /// 
    ///   When applicationFullPath is blank OR 
    ///   applicationFullPath contains invalid path characters OR 
    ///   applicationFullPath is not an absolute path 
    /// 
    /// 
    ///   If the firewall is not installed. 
    /// 
    /// 
    ///   If the specified application does not exist. 
    /// 
    public bool HasAuthorization(string applicationFullPath) 
    { 
     #region Parameter checking 
     if (applicationFullPath == null) 
      throw new ArgumentNullException("applicationFullPath"); 
     if (applicationFullPath.Trim().Length == 0) 
      throw new ArgumentException("applicationFullPath must not be blank"); 
     if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0) 
      throw new ArgumentException("applicationFullPath must not contain invalid path characters"); 
     if (!Path.IsPathRooted(applicationFullPath)) 
      throw new ArgumentException("applicationFullPath is not an absolute path"); 
     if (!File.Exists(applicationFullPath)) 
      throw new FileNotFoundException("File does not exist.", applicationFullPath); 
     // State checking 
     if (!IsFirewallInstalled) 
      throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed."); 

     #endregion 

     // Locate Authorization for this application 
     foreach (string appName in GetAuthorizedAppPaths()) 
     { 
      // Paths on windows file systems are not case sensitive. 
      if (appName.ToLower() == applicationFullPath.ToLower()) 
       return true; 
     } 

     // Failed to locate the given app. 
     return false; 

    } 

    /// 

    /// Retrieves a collection of paths to applications that are authorized. 
    /// 

    /// 
    /// 
    ///   If the Firewall is not installed. 
    /// 
    public ICollection GetAuthorizedAppPaths() 
    { 
     // State checking 
     if (!IsFirewallInstalled) 
      throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed."); 

     ArrayList list = new ArrayList(); 
     // Collect the paths of all authorized applications 
     foreach (INetFwAuthorizedApplication app in fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications) 
      list.Add(app.ProcessImageFileName); 

     return list; 
    } 
    #endregion 
} 

/// 

/// Describes a FirewallHelperException. 
/// 

/// 
/// 
/// 
public class FirewallHelperException : System.Exception 
{ 
    /// 

    /// Construct a new FirewallHelperException 
    /// 

    /// 
    public FirewallHelperException(string message) 
     : base(message) 
    { } 
} 

El recinto de seguridad de ClickOnce no presentó ningún problema.

+4

Parece que el enlace está roto. – JAG

+5

Este enlace funciona: http://web.archive.org/web/20070707110141/http://www.dot.net.nz/Default.aspx?tabid=42&mid=404&ctl=Details&ItemID=8 – Paya

+3

Este enlace funciona hoy: http://replay.web.archive.org/20081014105153/http://www.dot.net.nz/Default.aspx?tabid=42&mid=404&ctl=Details&ItemID=8 –

18

No estoy seguro si esta es la mejor manera, pero el funcionamiento netsh debería funcionar:

netsh firewall add allowedprogram C: \ MyApp \ MyApp.exe MiApl ENABLE

Creo que esto requiere permisos de administrador, sin embargo, por razones obvias :)

Edición: Simplemente no sé lo suficiente sobre ClickOnce para saber si puede o no ejecutar programas externos a través de él.

+0

personalmente me gusta esta solución. Es mucho más fácil invocar un proceso externo como este que hurgar con la API de Windows, especialmente cuando se utilizan elementos como Qt/C++. – jocull

+7

Esto depende del sistema operativo y no funciona con Win7 (está en desuso). Debes hacer algo más feo como: netsh advfirewall firewall agregar regla name = "allow messenger" dir = en program = "c: \ program files \ messenger \ msmsgs.exe" security = authnoencap action = permitir –

+1

Solo para agregar, para mayor completud, la implementación de ClickOnce no limita lo que su aplicación puede hacer una vez instalada, aunque puede intentar buscar actualizaciones al inicio. – Basic

11

Es posible acceder a los datos del firewall, mire los siguientes artículos.

La verdadera cuestión es que hace la caja de arena ClickOnce permite este tipo de acceso? Mi suposición sería que no es así. ¿Tal vez podrías usar un servicio web? (Para obtener más información acerca de los métodos de acceso a datos en ClickOnce ver Accessing Local and Remote Data in ClickOnce Applications)

+0

Si tiene algún problema para agregar la referencia hnetcfg en vs2010, consulte este enlace http://connect.microsoft.com/VisualStudio/feedback/details/575401/interop-netfwtypelib-dll-change – Alexandre

+0

obtengo una excepción de acceso denegado que he mencionado aquí http://stackoverflow.com/questions/8605710/get-my-application-to-be-allowed-access-through-firewall-using-c-sharp – PUG

3

La forma más sencilla que conozco sería utilizar netsh, puede simplemente eliminar la regla y volver a crearlo, o la creación de una regla de puerto, si el suyo está arreglado.
Here es una página que describe las opciones para su contexto de firewall.

+0

** netsh ** es específico de sistema operativo. No puede usar 1 comando netsh en Server 2003 y servidor 2008. – Achilles

1

La respuesta es que sólo permiten el software para ejecutar la administración de confianza privilegios. De vez en cuando, ALGUNOS software deben tener privilegios de administrador y realizar cambios sensibles en su sistema. También podría tener un disco duro de solo lectura de lo contrario ...

+0

Agregar una excepción de firewall no requiere privilegios elevados. – Bob77

+1

netsh advfirewall firewall agregar regla name = "Mi aplicación" dir = in action = allow program = "C: \ MyApp \ My App.exe" enable = yes La operación solicitada requiere elevation

0

Suponiendo que estamos utilizando un instalador de Estudio> Proyecto de instalación de Visual - Es necesario una clase de instalador como esto dentro de un montaje que está siendo instalado, y luego asegúrese de que agregue una acción personalizada para la "Salida primaria" en la fase de instalación.

using System.Collections; 
using System.ComponentModel; 
using System.Configuration.Install; 
using System.IO; 
using System.Diagnostics; 

namespace YourNamespace 
{ 
    [RunInstaller(true)] 
    public class AddFirewallExceptionInstaller : Installer 
    { 
     protected override void OnAfterInstall(IDictionary savedState) 
     { 
      base.OnAfterInstall(savedState); 

      var path = Path.GetDirectoryName(Context.Parameters["assemblypath"]); 
      OpenFirewallForProgram(Path.Combine(path, "YourExe.exe"), 
            "Your program name for display"); 
     } 

     private static void OpenFirewallForProgram(string exeFileName, string displayName) 
     { 
      var proc = Process.Start(
       new ProcessStartInfo 
        { 
         FileName = "netsh", 
         Arguments = 
          string.Format(
           "firewall add allowedprogram program=\"{0}\" name=\"{1}\" profile=\"ALL\"", 
           exeFileName, displayName), 
         WindowStyle = ProcessWindowStyle.Hidden 
        }); 
      proc.WaitForExit(); 
     } 
    } 
} 
+0

Esto funciona para mí –

+0

IMPORTANTE: ** "netsh firewall" está en desuso; ** use "netsh advfirewall firewall "en su lugar. Para obtener más información sobre el uso de los comandos" netsh advfirewall firewall " en lugar de "netsh firewall", consulte el artículo de KB 947709 en [enlace] (https://go.microsoft.com/fwlink/?linkid=121488). – antonio

Cuestiones relacionadas