Cambiar IP en regla de firewall GPO con PowerShell: guía y script

¿Necesitas cambiar rápidamente la IP de una regla de firewall dentro de una GPO y te topas con que Set-NetFirewallRule no acepta -GPOSession? Aquí tienes una guía práctica, segura y automatizable para hacerlo con PowerShell sin romper otras propiedades de la regla.

Índice

Resumen de la pregunta

El objetivo es reemplazar la dirección IP remota en una regla de firewall ya existente dentro de una GPO (Group Policy Object) usando PowerShell. Crear reglas nuevas con New-NetFirewallRule -GPOSession ... funciona, pero Set-NetFirewallRule -GPOSession falla porque ese cmdlet no expone el parámetro -GPOSession. ¿Cómo modificar entonces propiedades como -RemoteAddress sin salirnos de la GPO?

Respuesta corta

Abre una sesión sobre la GPO, elimina la regla y vuelve a crearla con la IP actualizada dentro de la misma sesión. Finalmente, guarda los cambios. Este patrón evita las limitaciones de Set-NetFirewallRule y mantiene el cambio encapsulado en la GPO.

# 1) Abrir sesión sobre la GPO (ajusta dominio y nombre de la GPO)
$GpoSession = Open-NetGPO -PolicyStore 'domain.local\NombreDeLaGPO'

2) (Opcional) Verificar que la regla existe en la GPO
Get-NetFirewallRule -GPOSession $GpoSession -DisplayName 'NombreDeLaRegla'

3) Eliminar la regla existente
Remove-NetFirewallRule -GPOSession $GpoSession -DisplayName 'NombreDeLaRegla'

4) Crear la regla nuevamente con la IP actualizada
New-NetFirewallRule -GPOSession $GpoSession `
  -DisplayName 'NombreDeLaRegla' `
  -RemoteAddress '192.168.1.100' `   # <-- nueva IP
  -Action Block                      # o Allow, según corresponda

5) Guardar los cambios en la GPO
Save-NetGPO -GPOSession $GpoSession

Por qué funciona esta estrategia

Set-NetFirewallRule está diseñado para modificar reglas en el almacén actual (habitualmente el equipo local) y no ofrece -GPOSession. En cambio, la familia de cmdlets Get-/New-/Remove- para reglas y filtros sí aceptan -GPOSession, lo que permite trabajar “offline” dentro de una GPO sin tocar la configuración local. Por eso, la forma consistente de actualizar propiedades como -RemoteAddress es recrear la regla dentro de la sesión de GPO.

Compatibilidad de cmdlets con -GPOSession

Para evitar confusiones, aquí tienes un resumen de los cmdlets más usados en este escenario y si aceptan -GPOSession:

Cmdlet¿Soporta -GPOSession?Uso típico en GPO
Open-NetGPOAbrir sesión de edición sobre una GPO
Save-NetGPOConfirmar / guardar los cambios en la GPO
Get-NetFirewallRuleConsultar reglas dentro de la GPO
New-NetFirewallRuleCrear reglas dentro de la GPO
Remove-NetFirewallRuleEliminar reglas dentro de la GPO
Set-NetFirewallRuleNoNo modifica reglas dentro de la GPO
Get-NetFirewallAddressFilterLeer filtros de direcciones de una regla en la GPO
Get-NetFirewallPortFilterLeer filtros de puertos/protocolo asociados
Get-NetFirewallApplicationFilterLeer filtros de programa
Get-NetFirewallServiceFilterLeer filtros de servicio
Get-NetFirewallICMPSettingLeer tipos ICMP asociados

Pasos detallados con PowerShell

  1. Abrir sesión de GPO: Open-NetGPO -PolicyStore 'dominio\NombreDeLaGPO' devuelve un identificador de sesión que usarás en todas las operaciones.
  2. Comprobar la regla: Valida que existe y revisa sus filtros actuales con Get-NetFirewallRule y la familia Get-NetFirewall*Filter.
  3. Eliminar y recrear: Ejecuta Remove-NetFirewallRule y luego New-NetFirewallRule copiando las propiedades relevantes y cambiando -RemoteAddress.
  4. Guardar: Save-NetGPO consolida los cambios en la GPO. Hasta entonces, todo es transaccional en la sesión.
  5. Propagar: La directiva se aplicará a los equipos objetivo en el siguiente ciclo de actualización de directivas o con gpupdate /force en los clientes.

Snippet listo para copiar: reemplazo directo de IP

$Gpo = 'domain.local\NombreDeLaGPO'
$Regla = 'NombreDeLaRegla'
$NuevaIP = '192.168.1.100' # admite coma, CIDR, Any, o LocalSubnet

\$GpoSession = Open-NetGPO -PolicyStore \$Gpo

(Opcional) Revisar filtros actuales

Get-NetFirewallRule -GPOSession \$GpoSession -DisplayName \$Regla |
Get-NetFirewallAddressFilter -GPOSession \$GpoSession

Borramos y recreamos (minimizando cambios)

Remove-NetFirewallRule -GPOSession \$GpoSession -DisplayName \$Regla

IMPORTANTE: replica aquí las propiedades clave que tu regla original tenía

New-NetFirewallRule -GPOSession \$GpoSession `  -DisplayName $Regla`
-RemoteAddress \$NuevaIP \`
-Action Block

Save-NetGPO -GPOSession \$GpoSession </code></pre>

<h2>Script reutilizable: actualiza la IP sin perder propiedades</h2>
<p>Para no olvidar ningún detalle, este script clona propiedades de la regla original (dirección, puertos, protocolo, programa, servicio, perfil, dirección, etc.) y solo cambia <code>-RemoteAddress</code>. Así reduces el riesgo de desviaciones entre la regla vieja y la nueva.</p>

<pre><code class="language-powershell">function Update-GpoFirewallRemoteAddress {
  [CmdletBinding(SupportsShouldProcess=$true)]
  param(
    [Parameter(Mandatory=$true)][string]$Domain,            # p.ej. domain.local
    [Parameter(Mandatory=$true)][string]$GpoName,           # p.ej. "Firewall - Servidores"
    [Parameter(Mandatory=$true)][string]$RuleDisplayName,   # nombre visible de la regla
    [Parameter(Mandatory=$true)][string[]]$NewRemoteAddress # admite coma, CIDR, Any, LocalSubnet
  )

  $policyStore = "{0}\{1}" -f $Domain, $GpoName
  $s = Open-NetGPO -PolicyStore $policyStore

  try {
    $rule = Get-NetFirewallRule -GPOSession $s -DisplayName $RuleDisplayName -ErrorAction Stop

    # Leer filtros asociados dentro de la GPO
    $addr = $rule | Get-NetFirewallAddressFilter -GPOSession $s
    $port = $rule | Get-NetFirewallPortFilter    -GPOSession $s
    $app  = $rule | Get-NetFirewallApplicationFilter -GPOSession $s
    $svc  = $rule | Get-NetFirewallServiceFilter     -GPOSession $s
    $icmp = $rule | Get-NetFirewallICMPSetting       -GPOSession $s

    # Construir parámetros para la nueva regla
    $params = @{
      GPOSession          = $s
      DisplayName         = $rule.DisplayName
      Description         = $rule.Description
      Group               = $rule.Group
      Profile             = $rule.Profile
      Direction           = $rule.Direction
      Enabled             = $rule.Enabled
      Action              = $rule.Action
      EdgeTraversalPolicy = $rule.EdgeTraversalPolicy
      InterfaceType       = $rule.InterfaceType
      RemoteAddress       = ($NewRemoteAddress -join ',')
    }

    if ($null -ne $addr.LocalAddress -and $addr.LocalAddress -ne 'Any') { $params['LocalAddress'] = $addr.LocalAddress }
    if ($null -ne $port.Protocol     -and $port.Protocol     -ne 'Any') { $params['Protocol']     = $port.Protocol }
    if ($null -ne $port.LocalPort    -and $port.LocalPort    -ne 'Any') { $params['LocalPort']    = $port.LocalPort }
    if ($null -ne $port.RemotePort   -and $port.RemotePort   -ne 'Any') { $params['RemotePort']   = $port.RemotePort }
    if ($null -ne $app.Program       -and $app.Program       -ne 'Any') { $params['Program']      = $app.Program }
    if ($null -ne $svc.Service       -and $svc.Service       -ne 'Any') { $params['Service']      = $svc.Service }
    if ($null -ne $icmp.IcmpType)                                   { $params['IcmpType']     = $icmp.IcmpType }

    if ($PSCmdlet.ShouldProcess("$policyStore / $RuleDisplayName", "Replace RemoteAddress")) {
      # Eliminar y recrear
      Remove-NetFirewallRule -GPOSession $s -DisplayName $RuleDisplayName -ErrorAction Stop
      New-NetFirewallRule @params
      Save-NetGPO -GPOSession $s
    }
  }
  catch {
    throw "No se pudo actualizar la regla '$RuleDisplayName' en la GPO '$GpoName': $($_.Exception.Message)"
  }
}

Ejemplo de uso:
Update-GpoFirewallRemoteAddress -Domain 'domain.local' -GpoName 'Firewall Servidores' `
-RuleDisplayName 'Bloqueo Saliente App X' -NewRemoteAddress @('192.168.1.100','10.10.10.0/24')
</code></pre>

<h3>Notas sobre el script</h3>
<ul>
  <li>Si la regla original estaba filtrada por <em>programa</em> o <em>servicio</em>, esos filtros se preservan.</li>
  <li>Los valores <em>Any</em> o <em>LocalSubnet</em> se respetan y no se añaden parámetros innecesarios.</li>
  <li>Solo se cambia <code>RemoteAddress</code>; todo lo demás queda igual.</li>
  <li>Incluye <code>SupportsShouldProcess</code>, de modo que puedes ejecutar con <code>-WhatIf</code> para un simulacro.</li>
</ul>

<h2>Actualizar varias reglas o múltiples IPs</h2>
<p>Si necesitas cambiar muchas reglas a la vez (por ejemplo, devaluar una IP antigua por una nueva), apóyate en patrones de nombre o grupos de reglas.</p>

<pre><code class="language-powershell">$Domain   = 'domain.local'
$GpoName  = 'Firewall - Servidores'
$Session  = Open-NetGPO -PolicyStore "$Domain\$GpoName"

Cambiar IP en todas las reglas cuyo DisplayName contenga "AppContable"
$targetRules = Get-NetFirewallRule -GPOSession $Session | Where-Object DisplayName -like 'AppContable'

foreach ($r in $targetRules) {
  $old = ($r | Get-NetFirewallAddressFilter -GPOSession $Session).RemoteAddress
  Write-Host "Regla: $($r.DisplayName) - RemoteAddress actual: $old"

  Remove-NetFirewallRule -GPOSession $Session -DisplayName $r.DisplayName

  New-NetFirewallRule -GPOSession $Session `
    -DisplayName $r.DisplayName `
    -Direction  $r.Direction `
    -Profile    $r.Profile `
    -Enabled    $r.Enabled `
    -Action     $r.Action `
    -RemoteAddress '10.20.30.40,10.20.30.0/24'  # nuevas IPs
}

Save-NetGPO -GPOSession $Session
</code></pre>

<h2>Buenas prácticas para cambios seguros</h2>
<ul>
  <li><strong>Documenta antes de tocar:</strong> exporta un “snapshot” antes de eliminar. Ejemplo:
    <pre><code class="language-powershell">Get-NetFirewallRule -GPOSession $GpoSession -DisplayName 'NombreDeLaRegla' |
  Select-Object DisplayName, Direction, Profile, Action, Enabled, Group, Description, InterfaceType |
  Format-List

Get-NetFirewallRule -GPOSession \$GpoSession -DisplayName 'NombreDeLaRegla' |
Get-NetFirewallAddressFilter -GPOSession \$GpoSession | Format-List

Get-NetFirewallRule -GPOSession \$GpoSession -DisplayName 'NombreDeLaRegla' |
Get-NetFirewallPortFilter -GPOSession \$GpoSession | Format-List </code></pre>

  </li>
  <li><strong>Versiona y hace “dry-run”:</strong> usa <code>-WhatIf</code> en funciones que lo soporten para validar el plan sin aplicar.</li>
  <li><strong>Guarda siempre:</strong> si no haces <code>Save-NetGPO</code>, nada se persiste en la GPO.</li>
  <li><strong>Propagación controlada:</strong> programa la ventana de mantenimiento y fuerza <code>gpupdate</code> en equipos críticos si procede.</li>
  <li><strong>Revisa WMI/seguridad de la GPO:</strong> asegúrate de que el ámbito de la GPO no cambió (filtros WMI, seguridad de aplicación, OU, etc.).</li>
</ul>

<h2>Plantilla de reemplazo con “rollback” simple</h2>
<p>En entornos críticos, puedes implementar una reversión inmediata si la creación falla. Este patrón guarda una copia de los parámetros y, si algo sale mal, restaura la regla original.</p>

<pre><code class="language-powershell">$Domain  = 'domain.local'
$GpoName = 'Firewall - Producción'
$Rule    = 'Permitir API Pago'
$NewAddr = '203.0.113.77'

$s = Open-NetGPO -PolicyStore "$Domain\$GpoName"

Snapshot de propiedades
$r    = Get-NetFirewallRule -GPOSession $s -DisplayName $Rule -ErrorAction Stop
$addr = $r | Get-NetFirewallAddressFilter -GPOSession $s
$port = $r | Get-NetFirewallPortFilter    -GPOSession $s
$app  = $r | Get-NetFirewallApplicationFilter -GPOSession $s
$svc  = $r | Get-NetFirewallServiceFilter     -GPOSession $s

$backup = @{
  DisplayName=$r.DisplayName; Description=$r.Description; Group=$r.Group
  Profile=$r.Profile; Direction=$r.Direction; Enabled=$r.Enabled
  Action=$r.Action; EdgeTraversalPolicy=$r.EdgeTraversalPolicy
  InterfaceType=$r.InterfaceType; LocalAddress=$addr.LocalAddress
  RemoteAddress=$addr.RemoteAddress; Protocol=$port.Protocol
  LocalPort=$port.LocalPort; RemotePort=$port.RemotePort
  Program=$app.Program; Service=$svc.Service
}

try {
  Remove-NetFirewallRule -GPOSession $s -DisplayName $Rule -ErrorAction Stop

  # Crear con RemoteAddress actualizado
  New-NetFirewallRule -GPOSession $s `
    -DisplayName $backup.DisplayName `
    -Description $backup.Description `
    -Group $backup.Group `
    -Profile $backup.Profile `
    -Direction $backup.Direction `
    -Enabled $backup.Enabled `
    -Action $backup.Action `
    -EdgeTraversalPolicy $backup.EdgeTraversalPolicy `
    -InterfaceType $backup.InterfaceType `
    -LocalAddress $backup.LocalAddress `
    -RemoteAddress $NewAddr `
    -Protocol $backup.Protocol `
    -LocalPort $backup.LocalPort `
    -RemotePort $backup.RemotePort `
    -Program $backup.Program `
    -Service $backup.Service

  Save-NetGPO -GPOSession $s
}
catch {
  Write-Warning "Error al crear la nueva regla. Intentando restaurar..."
  try {
    New-NetFirewallRule -GPOSession $s @backup
    Save-NetGPO -GPOSession $s
    Write-Warning "Regla restaurada desde backup."
  } catch {
    throw "Fallo la reversión: $($_.Exception.Message)"
  }
}
</code></pre>

<h2>Verificación y validación posterior</h2>
<ul>
  <li><strong>En la GPO:</strong>
    <pre><code class="language-powershell">Get-NetFirewallRule -GPOSession $s -DisplayName 'NombreDeLaRegla' |
  Get-NetFirewallAddressFilter -GPOSession $s | Select-Object LocalAddress,RemoteAddress

En clientes: tras aplicarse la GPO, valida con:

Get-NetFirewallRule -DisplayName 'NombreDeLaRegla' |
  Get-NetFirewallAddressFilter | Format-List

Registro de Eventos: si la regla afecta tráfico real, revisa el log del firewall (si está habilitado) para confirmar el efecto esperado.

Consejos prácticos y detalles finos

  • Varias IPs: separa por comas (-RemoteAddress '10.0.0.10,10.0.0.11').
  • Subredes: usa CIDR ('10.0.0.0/24'), o alias como LocalSubnet y Any.
  • Homogeneidad: si tu regla original tenía Direction, Profile, Program, Protocol, LocalPort, etc., reprodúcelos en la nueva regla.
  • Nombre vs. ID: si hay varias reglas con el mismo DisplayName, filtra por otros criterios (grupo, perfil, etc.) antes de eliminar.
  • Política de seguridad: valida que tienes permisos para editar la GPO y que los controladores de dominio replican correctamente.

Errores comunes y solución

SíntomaCausa probableSolución
Set-NetFirewallRule : A parameter cannot be found that matches parameter name 'GPOSession'Intento de modificar una regla en GPO con Set-*Usa el patrón Remove + New dentro de la sesión GPO y Save-NetGPO
Cambios no se reflejan en clientesNo se hizo Save-NetGPO o la GPO no aplica al equipoEjecuta Save-NetGPO, revisa vínculo de la GPO/seguridad/WMI, y aplica gpupdate
Regla recreada sin todas las propiedadesNo se copiaron filtros (puertos, programa, servicio, ICMP)Inspecciona con Get-NetFirewall*Filter y replica todas las propiedades relevantes
Conflictos por nombres duplicadosVarias reglas con el mismo nombre en la GPOFiltra por grupo/perfil/dirección y usa identificadores consistentes

Preguntas frecuentes

¿Puedo editar solo RemoteAddress sin borrar?
No dentro de la GPO con cmdlets estándar. Set-NetFirewallRule no expone -GPOSession. El patrón soportado es eliminar y crear de nuevo dentro de la misma sesión.

¿Puedo usar comodines o DNS en RemoteAddress?
Para firewall de Windows en GPO, utiliza IPs, rangos CIDR, LocalSubnet o Any. El uso de FQDN está limitado a escenarios concretos (por ejemplo, reglas de salida en perfiles recientes), pero no es general para todas las reglas. En contextos estrictos, traduce nombres a IPs o rangos.

¿Cómo gestiono múltiples GPOs?
Encapsula el patrón en una función y llama iterando la lista de GPOs. Abre, cambia, guarda y pasa a la siguiente GPO para minimizar tiempos de bloqueo.

¿Qué pasa si falla la creación de la regla nueva?
Implementa un pequeño “rollback” como se muestra: guarda un diccionario de propiedades y, si falla, restaura el estado anterior.

Checklist rápida

  • Identifica GPO y nombre exacto de la regla.
  • Abre sesión con Open-NetGPO.
  • Audita la regla y sus filtros.
  • Elimina la regla y recréala con la IP actualizada.
  • Replica todas las propiedades relevantes.
  • Ejecuta Save-NetGPO.
  • Valida en la GPO y en un cliente.
  • Programa la propagación (gpupdate si es necesario).

Atajos y variantes útiles

  • Varias IPs: -RemoteAddress '10.0.0.10,10.0.0.11'.
  • Subredes: -RemoteAddress '10.0.0.0/24'.
  • Alias: Any para todo, LocalSubnet para subred local.
  • Reglas de entrada/salida: conserva -Direction Inbound|Outbound según corresponda.
  • Perfiles: -Profile Domain,Private,Public como en la regla original.

Conclusión

Para cambiar la IP remota de una regla de firewall dentro de una GPO con PowerShell, la vía más limpia y fiable es trabajar con una sesión de GPO, eliminar la regla y volver a crearla con la nueva dirección. Esta técnica aprovecha los cmdlets que sí soportan -GPOSession, minimiza el riesgo de desconfiguración, permite automatizar cambios masivos y facilita la auditoría previa y posterior. Con los fragmentos de código de este artículo podrás aplicar el cambio en minutos y con control total.

Referencias prácticas y recordatorios

  • Empieza en el paso 2 si ya tienes la sesión en $GpoSession.
  • Para varias IPs, separa por comas; para subredes, usa CIDR.
  • Inspecciona filtros actuales con: Get-NetFirewallRule -GPOSession $GpoSession -DisplayName 'NombreDeLaRegla' | Get-NetFirewallAddressFilter -GPOSession $GpoSession
  • Replica en la regla nueva todas las propiedades relevantes que usaba la original.
Índice