{"id":353791,"date":"2024-09-30T13:50:28","date_gmt":"2024-09-30T13:50:28","guid":{"rendered":"https:\/\/www.ninjaone.com\/script-hub\/supervisar-conexiones-tcp-y-udp\/"},"modified":"2024-10-13T19:02:46","modified_gmt":"2024-10-13T19:02:46","slug":"supervisar-conexiones-tcp-y-udp","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/supervisar-conexiones-tcp-y-udp\/","title":{"rendered":"C\u00f3mo supervisar las conexiones TCP y UDP en Windows mediante PowerShell"},"content":{"rendered":"<p>En el panorama en constante evoluci\u00f3n de la seguridad inform\u00e1tica, mantener la visibilidad de las conexiones de red es primordial. Tanto si gestionas una gran red empresarial como si supervisas una peque\u00f1a o mediana empresa, es crucial saber qu\u00e9 <a href=\"https:\/\/www.ninjaone.com\/it-hub\/it-service-management\/what-is-an-ip-address\/\" target=\"_blank\" rel=\"noopener\">direcciones IP<\/a> se comunican activamente con tus sistemas.<\/p>\n<p>Este post profundiza en un script <a href=\"https:\/\/www.ninjaone.com\/it-hub\/endpoint-management\/what-is-powershell\/\" target=\"_blank\" rel=\"noopener\">PowerShell<\/a> especializado dise\u00f1ado para alertar a los administradores de direcciones IP espec\u00edficas que est\u00e1n escuchando o en un estado establecido. Esta herramienta tiene un valor incalculable para los profesionales de TI, los <a href=\"https:\/\/www.ninjaone.com\/es\/que-es-un-msp\" target=\"_blank\" rel=\"noopener\">proveedores de servicios gestionados (MSP)<\/a> y los equipos de seguridad que deseen reforzar sus capacidades de supervisi\u00f3n de la red. El siguiente contenido explica <span class=\"TextRun SCXW103397608 BCX0\" lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW103397608 BCX0\" data-ccp-parastyle=\"heading 1\"><strong>c\u00f3mo supervisar conexiones TCP y UDP en Windows usando PowerShell<\/strong>.<\/span><\/span><\/p>\n<h2>Comprender el script PowerShell<\/h2>\n<p>El script proporcionado sirve como mecanismo de alerta para conexiones de red, identificando direcciones IP especificadas en estado &#8216;Escuchando&#8217; o &#8216;Establecido&#8217;. Va m\u00e1s all\u00e1 de las comprobaciones b\u00e1sicas del firewall y ofrece informaci\u00f3n sobre las conexiones activas que pueden eludir los filtros de seguridad tradicionales. El script muestra detalles esenciales como la direcci\u00f3n, el ID del proceso, el estado, el protocolo, la direcci\u00f3n local y el nombre del proceso. Para quienes utilicen NinjaOne, los resultados pueden guardarse autom\u00e1ticamente en un campo personalizado para su posterior an\u00e1lisis.<\/p>\n<h2>Importancia para los profesionales de TI y los MSP<\/h2>\n<p>En el entorno digital actual, en el que las ciberamenazas est\u00e1n siempre presentes, es esencial tener un control granular de las conexiones de red. Este script responde a la necesidad de supervisar en tiempo real las actividades de la red, lo que permite a los profesionales de TI responder r\u00e1pidamente a posibles amenazas para la seguridad. Para los MSP que gestionan redes de varios clientes, este script ofrece un m\u00e9todo estandarizado para supervisar e informar sobre la actividad de la red, lo que garantiza una supervisi\u00f3n coherente y exhaustiva.<\/p>\n<h2>El script para supervisar conexiones TCP y UDP<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 5.1\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Alert on specified addresses that are Listening or Established and optionally save the results to a custom field.\r\n.DESCRIPTION\r\n    Will alert on addresses, regardless if a firewall is blocking them or not.\r\n    Checks for addresses that are in a 'Listen' or 'Established' state.\r\n    UDP is a stateless protocol and will not have a state.\r\n    Outputs the addresses, process ID, state, protocol, local address, and process name.\r\n    When a Custom Field is provided this will save the results to that custom field.\r\n\r\nPARAMETER: -IpAddress \"192.168.11.1, 192.168.1.1\/24\"\r\n    A comma separated list of IP Addresses to check. Can include IPv4 CIDR notation for ranges. IPv6 CIDR notation not supported. (e.g. 192.168.1.0\/24, 10.0.10.12)\r\n.EXAMPLE\r\n    -IpAddress \"192.168.1.0\/24, 10.0.10.12\"\r\n    ## EXAMPLE OUTPUT WITH IpAddress ##\r\n    [Info] Valid IP Address: 192.168.11.1\r\n    [Info] Valid IP Network: 192.168.1.1\/24\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 139, Remote Address: 0.0.0.0, Remote Port: None, PID: 4, Protocol: TCP, State: Listen, Process: System\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 138, Remote Address: None, Remote Port: None, PID: 4, Protocol: UDP, State: None, Process: System\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 137, Remote Address: None, Remote Port: None, PID: 4, Protocol: UDP, State: None, Process: System\r\n\r\nPARAMETER: -CustomField \"ReplaceMeWithAnyMultilineCustomField\"\r\n    Name of the custom field to save the results to.\r\n.EXAMPLE\r\n    -IpAddress \"192.168.11.1, 192.168.1.1\/24\" -CustomField \"ReplaceMeWithAnyMultilineCustomField\"\r\n    ## EXAMPLE OUTPUT WITH CustomField ##\r\n    [Info] Valid IP Address: 192.168.11.1\r\n    [Info] Valid IP Network: 192.168.1.1\/24\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 139, Remote Address: 0.0.0.0, Remote Port: None, PID: 4, Protocol: TCP, State: Listen, Process: System\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 138, Remote Address: None, Remote Port: None, PID: 4, Protocol: UDP, State: None, Process: System\r\n    [Alert] Found Local Address: 192.168.1.18, Local Port: 137, Remote Address: None, Remote Port: None, PID: 4, Protocol: UDP, State: None, Process: System\r\n    \r\n    [Info] Saving results to custom field: ReplaceMeWithAnyMultilineCustomField\r\n    [Info] Results saved to custom field: ReplaceMeWithAnyMultilineCustomField\r\n.OUTPUTS\r\n    None\r\n.NOTES\r\n    Supported Operating Systems: Windows 10\/Windows Server 2016 or later with PowerShell 5.1\r\n    Release Notes: Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [Parameter()]\r\n    [String]$IpAddress,\r\n    [String]$CustomFieldName\r\n)\r\n\r\nbegin {\r\n    function Test-IsElevated {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)\r\n    }\r\n    function Set-NinjaProperty {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n    \r\n        $Characters = $Value | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n        if ($Characters -ge 10000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded, value is greater than 10,000 characters.\")\r\n        }\r\n        \r\n        # If we're requested to set the field value for a Ninja document we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n        \r\n        # This is a list of valid fields that can be set. If no type is given, it will be assumed that the input doesn't need to be changed.\r\n        $ValidFields = \"Attachment\", \"Checkbox\", \"Date\", \"Date or Date Time\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \"MultiSelect\", \"Phone\", \"Secure\", \"Text\", \"Time\", \"URL\", \"WYSIWYG\"\r\n        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning \"$Type is an invalid type! Please check here for valid types. https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\" }\r\n        \r\n        # The field below requires additional information to be set\r\n        $NeedsOptions = \"Dropdown\"\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n        \r\n        # If an error is received it will have an exception property, the function will exit with that error information.\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # The below type's require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # While it's highly likely we were given a value like \"True\" or a boolean datatype it's better to be safe than sorry.\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Ninjarmm-cli expects the  Date-Time to be in Unix Epoch time so we'll convert it here.\r\n                $Date = (Get-Date $Value).ToUniversalTime()\r\n                $TimeSpan = New-TimeSpan (Get-Date \"1970-01-01 00:00:00\") $Date\r\n                $NinjaValue = $TimeSpan.TotalSeconds\r\n            }\r\n            \"Dropdown\" {\r\n                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a guid.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID\r\n        \r\n                if (-not $Selection) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            default {\r\n                # All the other types shouldn't require additional work on the input.\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.\r\n        if ($DocumentName) {\r\n            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2&gt;&amp;1\r\n        }\r\n        else {\r\n            $CustomField = $NinjaValue | Ninja-Property-Set-Piped -Name $Name 2&gt;&amp;1\r\n        }\r\n        \r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n    function Test-IPNetwork {\r\n        param([string]$Text)\r\n        $Ip, $Prefix = $Text -split '\/'\r\n        $Ip -as [System.Net.IPAddress] -and\r\n        $Prefix -as [int] -and $Prefix -ge 0 -and $Prefix -le 32\r\n    }\r\n    function Get-IPNetwork {\r\n        [CmdletBinding()]\r\n    \r\n        Param(\r\n            [Parameter(Mandatory, Position = 0)]\r\n            [ValidateScript({ $_ -eq ([IPAddress]$_).IPAddressToString })]\r\n            [string]$IPAddress,\r\n    \r\n            [Parameter(Mandatory, Position = 1, ParameterSetName = \"SubnetMask\")]\r\n            [ValidateScript({ $_ -eq ([IPAddress]$_).IPAddressToString })]\r\n            [ValidateScript({\r\n                    $SMReversed = [IPAddress]$_\r\n                    $SMReversed = $SMReversed.GetAddressBytes()\r\n                    [array]::Reverse($SMReversed)\r\n                    [IPAddress]$SMReversed = $SMReversed\r\n                    [convert]::ToString($SMReversed.Address, 2) -match \"^[1]*0{0,}$\"\r\n                })]\r\n            [string]$SubnetMask,\r\n    \r\n            [Parameter(Mandatory, Position = 1, ParameterSetName = \"CIDRNotation\")]\r\n            [ValidateRange(0, 32)]\r\n            [int]$PrefixLength,\r\n    \r\n            [switch]$ReturnAllIPs\r\n        )\r\n    \r\n        [IPAddress]$IPAddress = $IPAddress\r\n    \r\n        if ($SubnetMask) {\r\n            [IPAddress]$SubnetMask = $SubnetMask\r\n            $SMReversed = $SubnetMask.GetAddressBytes()\r\n            [array]::Reverse($SMReversed)\r\n            [IPAddress]$SMReversed = $SMReversed\r\n    \r\n            [int]$PrefixLength = [convert]::ToString($SMReversed.Address, 2).replace(0, '').length\r\n        } \r\n        else {\r\n            [IPAddress]$SubnetMask = ([Math]::Pow(2, $PrefixLength) - 1) * [Math]::Pow(2, (32 - $PrefixLength))\r\n        }\r\n    \r\n        \r\n        $FullMask = [UInt32]'0xffffffff'\r\n        $WildcardMask = [IPAddress]($SubnetMask.Address -bxor $FullMask)\r\n        $NetworkId = [IPAddress]($IPAddress.Address -band $SubnetMask.Address)\r\n        $Broadcast = [IPAddress](($FullMask - $NetworkId.Address) -bxor $SubnetMask.Address)\r\n    \r\n        # Used for determining first usable IP Address\r\n        $FirstIPByteArray = $NetworkId.GetAddressBytes()\r\n        [Array]::Reverse($FirstIPByteArray)\r\n    \r\n        # Used for determining last usable IP Address\r\n        $LastIPByteArray = $Broadcast.GetAddressBytes()\r\n        [Array]::Reverse($LastIPByteArray)\r\n    \r\n        # Handler for \/31, \/30 CIDR prefix values, and default for all others.\r\n        switch ($PrefixLength) {\r\n            31 {\r\n                $TotalIPs = 2\r\n                $UsableIPs = 2\r\n                $FirstIP = $NetworkId\r\n                $LastIP = $Broadcast\r\n                $FirstIPInt = ([IPAddress]$FirstIPByteArray).Address\r\n                $LastIPInt = ([IPAddress]$LastIPByteArray).Address\r\n                break\r\n            }\r\n    \r\n            32 {\r\n                $TotalIPs = 1\r\n                $UsableIPs = 1\r\n                $FirstIP = $IPAddress\r\n                $LastIP = $IPAddress\r\n                $FirstIPInt = ([IPAddress]$FirstIPByteArray).Address\r\n                $LastIPInt = ([IPAddress]$LastIPByteArray).Address\r\n                break\r\n            }\r\n    \r\n            default {\r\n    \r\n                # Usable Address Space\r\n                $TotalIPs = [Math]::pow(2, (32 - $PrefixLength))\r\n                $UsableIPs = $TotalIPs - 2\r\n    \r\n                # First usable IP\r\n                $FirstIPInt = ([IPAddress]$FirstIPByteArray).Address + 1\r\n                $FirstIP = [IPAddress]$FirstIPInt\r\n                $FirstIP = ($FirstIP).GetAddressBytes()\r\n                [Array]::Reverse($FirstIP)\r\n                $FirstIP = [IPAddress]$FirstIP\r\n    \r\n                # Last usable IP\r\n                $LastIPInt = ([IPAddress]$LastIPByteArray).Address - 1\r\n                $LastIP = [IPAddress]$LastIPInt\r\n                $LastIP = ($LastIP).GetAddressBytes()\r\n                [Array]::Reverse($LastIP)\r\n                $LastIP = [IPAddress]$LastIP\r\n            }\r\n        }\r\n    \r\n        $AllIPs = if ($ReturnAllIPs) {\r\n    \r\n            if ($UsableIPs -ge 500000) {\r\n                Write-Host ('[Warn] Generating an array containing {0:N0} IPs, this may take a little while' -f $UsableIPs)\r\n            }\r\n    \r\n            $CurrentIPInt = $FirstIPInt\r\n    \r\n            Do {\r\n                $IP = [IPAddress]$CurrentIPInt\r\n                $IP = ($IP).GetAddressBytes()\r\n                [Array]::Reverse($IP) | Out-Null\r\n                $IP = ([IPAddress]$IP).IPAddressToString\r\n                $IP\r\n    \r\n                $CurrentIPInt++\r\n    \r\n            } While ($CurrentIPInt -le $LastIPInt)\r\n        }\r\n    \r\n    \r\n        $obj = [PSCustomObject]@{\r\n            NetworkId    = ($NetworkId).IPAddressToString\r\n            Broadcast    = ($Broadcast).IPAddressToString\r\n            SubnetMask   = ($SubnetMask).IPAddressToString\r\n            PrefixLength = $PrefixLength\r\n            WildcardMask = ($WildcardMask).IPAddressToString\r\n            FirstIP      = ($FirstIP).IPAddressToString\r\n            LastIP       = ($LastIP).IPAddressToString\r\n            TotalIPs     = $TotalIPs\r\n            UsableIPs    = $UsableIPs\r\n            AllIPs       = $AllIPs\r\n        }\r\n    \r\n        Write-Output $obj\r\n    }\r\n}\r\nprocess {\r\n    if (-not (Test-IsElevated)) {\r\n        Write-Error -Message \"Access Denied. Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n    if ($env:ipAddress -and $env:ipAddress -ne 'null') {\r\n        $IpAddress = $env:ipAddress\r\n    }\r\n    if ($env:customFieldName -and $env:customFieldName -ne 'null') {\r\n        $CustomFieldName = $env:customFieldName\r\n    }\r\n\r\n    # Parse the Addresses to check\r\n    $Addresses = if ($IpAddress) {\r\n        # Validate the IP Address\r\n        $IpAddress -split ',' | ForEach-Object {\r\n            \"$_\".Trim()\r\n        } | ForEach-Object {\r\n            if (($_ -as [System.Net.IPAddress])) {\r\n                Write-Host \"[Info] Valid IP Address: $_\"\r\n                [System.Net.IPAddress]::Parse($_)\r\n            }\r\n            elseif ($(Test-IPNetwork $_)) {\r\n                Write-Host \"[Info] Valid IP Network: $_\"\r\n                $Address, $PrefixLength = $_ -split '\/'\r\n                try {\r\n                    Get-IPNetwork -IPAddress $Address -PrefixLength $PrefixLength -ReturnAllIPs | Select-Object -ExpandProperty AllIPs\r\n                }\r\n                catch {\r\n                    Write-Host \"[Error] Invalid IP CIDR: $_\"\r\n                    exit 1\r\n                }\r\n            }\r\n            else {\r\n                Write-Host \"[Error] Invalid IP Address: $_\"\r\n                exit 1\r\n            }\r\n        }\r\n    }\r\n    else { $null }\r\n\r\n    # Get the open ports\r\n    $FoundAddresses = $(\r\n        Get-NetTCPConnection | Select-Object @(\r\n            'LocalAddress'\r\n            'LocalPort'\r\n            @{Name = \"RemoteAddress\"; Expression = { if ($_.RemoteAddress) { $_.RemoteAddress }else { \"None\" } } }\r\n            @{Name = \"RemotePort\"; Expression = { if ($_.RemotePort) { $_.RemotePort }else { \"None\" } } }\r\n            'State'\r\n            @{Name = \"Protocol\"; Expression = { \"TCP\" } }\r\n            'OwningProcess'\r\n            @{Name = \"Process\"; Expression = { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName } }\r\n        )\r\n        Get-NetUDPEndpoint | Select-Object @(\r\n            'LocalAddress'\r\n            'LocalPort'\r\n            @{Name = \"RemoteAddress\"; Expression = { \"None\" } }\r\n            @{Name = \"RemotePort\"; Expression = { \"None\" } }\r\n            @{Name = \"State\"; Expression = { \"None\" } }\r\n            @{Name = \"Protocol\"; Expression = { \"UDP\" } }\r\n            'OwningProcess'\r\n            @{Name = \"Process\"; Expression = { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName } }\r\n        )\r\n    ) | Where-Object {\r\n        $(\r\n            &lt;# When Addresses are specified select just those addresses. #&gt;\r\n            if ($Addresses) {\r\n                $_.LocalAddress -in $Addresses -or\r\n                $_.RemoteAddress -in $Addresses\r\n            }\r\n            else { $true }\r\n        ) -and\r\n        (\r\n            &lt;# Filter out anything that isn't listening or established. #&gt;\r\n            $(\r\n                $_.Protocol -eq \"TCP\" -and\r\n                $(\r\n                    $_.State -eq \"Listen\" -or\r\n                    $_.State -eq \"Established\"\r\n                )\r\n            ) -or\r\n            &lt;# UDP is stateless, return all UDP connections. #&gt;\r\n            $_.Protocol -eq \"UDP\"\r\n        )\r\n    } | Sort-Object LocalAddress, RemoteAddress | Select-Object * -Unique\r\n\r\n    if (-not $FoundAddresses -or $FoundAddresses.Count -eq 0) {\r\n        Write-Host \"[Info] No Addresses were found listening or established with the specified network or address\"\r\n    }\r\n\r\n    # Output the found Addresses\r\n    $FoundAddresses | ForEach-Object {\r\n        Write-Host \"[Alert] Found Local Address: $($_.LocalAddress), Local Port: $($_.LocalPort), Remote Address: $($_.RemoteAddress), Remote Port: $($_.RemotePort), PID: $($_.OwningProcess), Protocol: $($_.Protocol), State: $($_.State), Process: $($_.Process)\"\r\n    }\r\n    # Save the results to a custom field if one was provided\r\n    if ($CustomFieldName -and $CustomFieldName -ne 'null') {\r\n        try {\r\n            Write-Host \"[Info] Saving results to custom field: $CustomFieldName\"\r\n            Set-NinjaProperty -Name $CustomFieldName -Value $(\r\n                $FoundAddresses | ForEach-Object {\r\n                    \"Local Address: $($_.LocalAddress), Local Port: $($_.LocalPort), Remote Address: $($_.RemoteAddress), Remote Port: $($_.RemotePort), PID: $($_.OwningProcess), Protocol: $($_.Protocol), State: $($_.State), Process: $($_.Process)\"\r\n                } | Out-String\r\n            )\r\n            Write-Host \"[Info] Results saved to custom field: $CustomFieldName\"\r\n        }\r\n        catch {\r\n            Write-Host $_.Exception.Message\r\n            Write-Host \"[Warn] Failed to save results to custom field: $CustomFieldName\"\r\n            exit 1\r\n        }\r\n    }\r\n}\r\nend {\r\n    \r\n    \r\n    \r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"blog-cta-new blog-cta-style-1\"><div class=\"cta-left\"><h2><\/h2><p><\/p><\/div><div class=\"cta-right\"><a class=\"button\" href=\"\"><\/a><\/div><\/div>\n<h2>C\u00f3mo funciona el script<\/h2>\n<h3><em>1. Configuraci\u00f3n inicial<\/em><\/h3>\n<p>El script requiere la versi\u00f3n 5.1 o posterior de PowerShell y est\u00e1 pensado para su uso en Windows 10 o Windows Server 2016 y versiones posteriores. Comienza comprobando si el script se est\u00e1 ejecutando con privilegios de administrador, necesarios para acceder a la informaci\u00f3n de la conexi\u00f3n de red.<\/p>\n<h3><em>2. An\u00e1lisis sint\u00e1ctico de par\u00e1metros<\/em><\/h3>\n<p>El script acepta dos par\u00e1metros principales: -IpAddress y -CustomField. El par\u00e1metro -IpAddress permite especificar una lista de direcciones IP o rangos de IP anotados con CIDR para monitorizar. El par\u00e1metro -CustomField es opcional y se utiliza para guardar los resultados en un campo personalizado de NinjaOne.<\/p>\n<h3><em>3. Validaci\u00f3n de direcciones<\/em><\/h3>\n<p>Una vez proporcionados los par\u00e1metros, el script valida cada direcci\u00f3n IP o rango de red. Si detecta una direcci\u00f3n o red v\u00e1lida, procede a recuperar todas las IP correspondientes dentro de ese rango.<\/p>\n<h3><em>4. Supervisi\u00f3n de las conexiones de red<\/em><\/h3>\n<p>El script utiliza los cmdlets Get-NetTCPConnection y Get-NetUDPEndpoint para capturar todas las conexiones TCP y UDP actuales del sistema. Filtra estas conexiones para identificar aquellas en estado \u00abEscuchando\u00bb o \u00abEstablecido\u00bb para TCP, y captura todas las conexiones UDP debido a su naturaleza sin estado.<\/p>\n<h3><em>5. Salida y ahorro opcional<\/em><\/h3>\n<p>Las conexiones identificadas se muestran entonces en un formato estructurado, mostrando detalles como direcciones locales y remotas, puertos, ID de procesos, protocolos y estados. Si se especifica un campo personalizado, el script guarda estos resultados para su posterior an\u00e1lisis dentro de NinjaOne.<\/p>\n<h2>Caso pr\u00e1ctico: aplicaciones reales<\/h2>\n<p>Consideremos un escenario en el que un MSP gestiona la infraestructura de TI de una empresa de servicios financieros. La empresa tiene estrictos requisitos de seguridad y necesita supervisar todas las conexiones entrantes y salientes para evitar accesos no autorizados. El MSP despliega este script en todos los servidores y endpoints, especificando los rangos de IP internos de la empresa para garantizar que s\u00f3lo los dispositivos autorizados se comunican con la red. Si el script detecta una conexi\u00f3n desde una IP no autorizada, alerta al administrador, que puede tomar medidas inmediatas para investigar y mitigar el riesgo.<\/p>\n<h2>Comparaci\u00f3n con otros m\u00e9todos<\/h2>\n<p>Mientras que otras herramientas como Wireshark o Netstat pueden proporcionar informaci\u00f3n detallada sobre el tr\u00e1fico de red, este script de PowerShell ofrece un enfoque simplificado y automatizado. A diferencia de Wireshark, que requiere un an\u00e1lisis manual de los paquetes, este script alerta autom\u00e1ticamente sobre conexiones espec\u00edficas, lo que lo hace m\u00e1s accesible para una supervisi\u00f3n continua. Comparado con Netstat, el script a\u00f1ade valor filtrando e informando de las conexiones en un formato m\u00e1s estructurado y procesable.<\/p>\n<h2>Preguntas frecuentes<\/h2>\n<h3>P: \u00bfEste script monitorizar direcciones IPv6?<\/h3>\n<p>R: Actualmente, el script s\u00f3lo admite direcciones y redes IPv4. La compatibilidad con IPv6 requerir\u00eda modificaciones en el script para gestionar el diferente formato de las direcciones.<\/p>\n<h3>P: \u00bfQu\u00e9 ocurre si se introduce una direcci\u00f3n IP inv\u00e1lida?<\/h3>\n<p>R: El script incluye comprobaciones de validaci\u00f3n y detendr\u00e1 la ejecuci\u00f3n si se detecta una direcci\u00f3n IP o una red no v\u00e1lidas, proporcionando un mensaje de error al usuario.<\/p>\n<h3>P: \u00bfC\u00f3mo se guardan los resultados en NinjaOne?<\/h3>\n<p>R: Si se proporciona el par\u00e1metro -CustomField, el script utiliza la CLI de NinjaOne para guardar los resultados en el campo personalizado especificado, asegurando que los <a href=\"https:\/\/www.ninjaone.com\/es\/blog\/plan-de-proteccion-de-datos-pasos-para-la-creacion\/\" target=\"_blank\" rel=\"noopener\">datos<\/a> sean accesibles para futuras referencias o informes.<\/p>\n<h2>Implicaciones de los resultados<\/h2>\n<p>El resultado de este script puede tener implicaciones significativas para la seguridad inform\u00e1tica. Al identificar y alertar sobre las conexiones activas, los profesionales de TI pueden detectar r\u00e1pidamente accesos no autorizados, posibles comunicaciones de malware o servicios mal configurados. El uso regular de este script mejora la visibilidad de las actividades de la red, contribuyendo a un entorno inform\u00e1tico m\u00e1s seguro y resistente.<\/p>\n<h2>Buenas pr\u00e1cticas para utilizar el script<\/h2>\n<ol>\n<li><strong>Ejecuta el script con regularidad<\/strong>: programa el script para que se ejecute a intervalos regulares, garantizando as\u00ed la supervisi\u00f3n continua de las conexiones de red.<\/li>\n<li><strong>Int\u00e9gralo con NinjaOne<\/strong>: aprovecha las capacidades de NinjaOne para almacenar y analizar los resultados, lo que permite la supervisi\u00f3n a largo plazo y el an\u00e1lisis de tendencias.<\/li>\n<li><strong>Ad\u00e1ptalo a tu entorno<\/strong>: modifica el script seg\u00fan sea necesario para adaptarlo a rangos de IP espec\u00edficos o a requisitos de registro adicionales.<\/li>\n<li><strong>Prueba en un entorno seguro<\/strong>: antes de desplegarlo en producci\u00f3n, prueba el script en un entorno controlado para asegurarte de que funciona como deber\u00eda.<\/li>\n<\/ol>\n<h2>Reflexiones finales<\/h2>\n<p>Este script PowerShell ofrece una soluci\u00f3n robusta para supervisar conexiones TCP y UDP en sistemas Windows. Al integrarlo en tu conjunto de herramientas de monitorizaci\u00f3n de red, en particular dentro de <a href=\"https:\/\/www.ninjaone.com\/es\/\" target=\"_blank\" rel=\"noopener\">NinjaOne<\/a>, puedes lograr una mayor visibilidad y control sobre tu entorno de TI. Para los profesionales de TI y MSP, este script proporciona un enfoque pr\u00e1ctico para salvaguardar la integridad de la red, permitiendo respuestas proactivas a las amenazas potenciales.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"","_lmt_disable":""},"operating_system":[4212],"use_cases":[4263],"class_list":["post-353791","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/353791","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=353791"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=353791"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=353791"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=353791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}