Skip to content

Swapping Between Multiple Bound IPs with PowerShell

    Why?

    A client had a requirement for a Windows service to swap over its public IP to essentially change its outbound IP address at will, without impacting any existing connections or connectivity. This posed an interesting challenge, as essentially the idea would be to swap to the ‘next IP address’ in a list of already bound IPs on an existing adapter.

    There is a partial implementation of this at the Microsoft DevBlogs (Use PowerShell to Change IP Behavior with SkipAsSource) which served as inspiration for this article. The idea is that you want to swap the SkipAsSource property between the adapters, and this allows you to keep all existing connections open while changing the outbound IP that the server connects on.

    You could then set up a outbound NAT rule to tie the primary IP to a different outbound IP address, to allow the server to go out via multiple IPs, or manage the outbound connections however you want.

    The Setup

    To set this up, configure a Windows adapter with multiple IP address. Under Advanced TCP/IP settings configure two addresses, ensuring that they have the same subnet mask.

    Please note that the primary and first ethernet adapter is used. If you would like to name your ethernet adapter, change the $_.InterfaceName -like to -eq.

    Code

    # Get the primary network adapter
    $adapter = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' -and $_.InterfaceName -like '*Ethernet*' } | Select-Object -First 1
    
    if ($adapter) {
    
        # Get all IPv4 IP addresses on the specified interface
        $ipAddresses = Get-NetIPAddress -InterfaceAlias $adapter.InterfaceAlias -AddressFamily IPv4 | Sort-Object IPAddress
    
        # Identify the current primary IP (SkipAsSource is false)
        $currentPrimary = $ipAddresses | Where-Object {$_.SkipAsSource -eq $false} | Select-Object -First 1
    
        if ($currentPrimary) {
            # Find the index of the current primary IP
            $currentIndex = $ipAddresses.IndexOf($currentPrimary)
    
            # Calculate the index of the next IP to set as primary
            $nextIndex = ($currentIndex + 1) % $ipAddresses.Count
    
            # Get the next IP to be set as primary
            $nextPrimary = $ipAddresses[$nextIndex]
    
            # Set the current primary's SkipAsSource to true
            Set-NetIPAddress -IPAddress $currentPrimary.IPAddress -PrefixLength $currentPrimary.PrefixLength -InterfaceAlias $adapter.InterfaceAlias -SkipAsSource $true -Confirm:$false
    
            # Set the next primary's SkipAsSource to false
            Set-NetIPAddress -IPAddress $nextPrimary.IPAddress -PrefixLength $nextPrimary.PrefixLength -InterfaceAlias $adapter.InterfaceAlias -SkipAsSource $false -Confirm:$false
    
            Write-Host "Swapped primary IP from $($currentPrimary.IPAddress) to $($nextPrimary.IPAddress)."
        } else {
            Write-Host "No primary IP address set with SkipAsSource false on the $netInterface interface. Setting the first IP as primary."
            # If no primary is found (unlikely), set the first one as primary
            $firstIP = $ipAddresses[0]
            Set-NetIPAddress -IPAddress $firstIP.IPAddress -PrefixLength $firstIP.PrefixLength -InterfaceAlias $adapter.InterfaceAlias -SkipAsSource $false -Confirm:$false
        }
    }
    
    
    
    

    Shameless Plug: Looking for custom PowerShell hackery? Set our PS var to $SkipAsSource = $false, and reach out!

    Leave a Reply

    Your email address will not be published. Required fields are marked *