{"id":86613,"date":"2021-01-31T14:00:49","date_gmt":"2021-01-31T22:00:49","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/scripting\/?p=86613"},"modified":"2023-03-31T06:11:05","modified_gmt":"2023-03-31T13:11:05","slug":"testing-rpc-ports-with-powershell-and-yes-its-as-much-fun-as-it-sounds","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/testing-rpc-ports-with-powershell-and-yes-its-as-much-fun-as-it-sounds\/","title":{"rendered":"Testing RPC ports with PowerShell (and yes, it&#8217;s as much fun as it sounds!) New and Improved!!"},"content":{"rendered":"<p><strong>Summary<\/strong>: Using PowerShell to identify RPC ports in use by capturing content from PowerShell<\/p>\n<p>We&#8217;d like to introduce you today to one of our newest bloggers!\u00a0 It&#8217;s a froopingly awesome friend of ours, <a href=\"https:\/\/social.msdn.microsoft.com\/profile\/Joel%20Vickery,%20PFE\" target=\"_blank\" rel=\"noopener noreferrer\">Joel Vickery, PFE<\/a>.\u00a0 (did I mention Dr. Scripto is a big fan of books written by Douglas Adams?&#8230;.oops!) Take it away Joel!<\/p>\n<p>Thanks Doc!\u00a0 So hey everybody! What do you do when you have to troubleshoot the dreaded &#8220;RPC Unavailable&#8221; error 1722, which rears its ugly head anywhere from Active Directory replication to Configuration Manager Distribution Point installations, and many other places in between? We have the answer for you!<\/p>\n<p>Updated 10\/31\/2021: When I originally created this script many years back, it bugged me that I had a dependency on a tool that had to be installed on the system to help with the RPC Endpoint mapper. Things like that stick with me (for years\u2026it\u2019s a curse!) but I finally found a solution to this dilemma in a script published by another Microsoft Employee, Ryan Ries way back in 2014. I was able to make some changes to his script, which utilizes native RPC calls and allows this all to work without PortQry (no offense, still love Sysinternals!). The rest of the post below will be updated to reflect the changes and many thanks to Ryan for solving this issue. Hopefully it helps when you need to troubleshoot RPC and are dealing with admins that start developing new twitches and ticks when you want to install something on their systems to troubleshoot\u2026no longer an issue after today!<\/p>\n<p>To help prevent this from becoming a blame-pointing cage match between the System Admins and the Network Folks (we all know the Sys Admins would win anyway), I&#8217;m writing this post to help put some structure around troubleshooting this type of issue so that you have more facts to take to the conversation. &#8220;I think it&#8217;s a firewall issue&#8221; doesn&#8217;t get you very far in my experience.<\/p>\n<p>RPC communication is one of the tougher firewall problems since most firewall folks want to know\u00a0exactly which ports you need open.\u00a0With RPC, they are usually given a range of ports from 49152 to 65535 to open on the firewall.\u00a0 There are usually predefined rules on firewalls, WAN accelerators, and the various devices that traffic hops through to get to its destination.\u00a0 They do not always work as planned.<\/p>\n<p>To give you the simplest example I can think of, RPC sort of works like the concierge desk at a hotel.\u00a0 You walk up and ask the person at the desk for the information about services at the hotel, like the gym or the swimming pool.\u00a0 In our scenario, that person at the desk is RPC Endpoint Mapper on port 135 and they direct you to the services that are listening on the ephemeral ports. I&#8217;m just barely breaking the surface on RPC in this post.\u00a0 If you want to get the full picture, take a look at what, in my opinion, is the best explanation about how RPC works in gory detail, written by Ned Pyle (and his dogs) at the link below: <a href=\"https:\/\/blogs.technet.microsoft.com\/askds\/2012\/01\/24\/rpc-over-itpro\/\">https:\/\/blogs.technet.microsoft.com\/askds\/2012\/01\/24\/rpc-over-itpro\/<\/a><\/p>\n<p>I see a lot of administrators attempting to diagnose this network connectivity by looking up the RPC ports (135 &amp; 49152-65535) and then attempting to connect to random ports in the ephemeral range, hopefully this post will help with isolating the ports that are truly listening on the server.<\/p>\n<p>The way I normally troubleshoot this type of network connectivity is with the SysInternals PortQry.exe utility, which can be downloaded from the Microsoft website. As mentioned above, the dependency on PortQry.exe has been removed but I am leaving this information in the post since there is big value in using PortQry. To begin, run the following command to query the RPC Port Mapper on the remote machine, this will return the ports in the ephemeral range that the machine is actively listening on for RPC services:<\/p>\n<pre class=\"lang:ps decode:true \">Portqry.exe -n 169.254.0.10 -e 135\n\n(PARTIAL OUTPUT BELOW)\n\nQuerying target system called:\n\n169.254.0.10\n\nAttempting to resolve IP address to a name...\n\nIP address resolved to DC1.contoso.com\n\nquerying...\n\nTCP port 135 (epmap service): LISTENING\n\nUsing ephemeral source port\n\nQuerying Endpoint Mapper Database...\n\nServer's response:\n\nUUID: d95afe70-a6d5-4259-822e-2c84da1ddb0d\n\nncacn_ip_tcp:169.254.0.10[49664]\n\nUUID: 50abc2a4-574d-40b3-9d66-ee4fd5fba076\n\nncacn_ip_tcp:169.254.0.10[64555]\n\nUUID: 897e2e5f-93f3-4376-9c9c-fd2277495c27 Frs2 Service\n\nncacn_ip_tcp:169.254.0.10[64528]\n\nUUID: 367abb81-9844-35f1-ad32-98f038001003\n\nncacn_ip_tcp:169.254.0.10[64502]\n\nUUID: c9ac6db5-82b7-4e55-ae8a-e464ed7b4277 Impl friendly name\n\nncacn_ip_tcp:169.254.0.10[49668]\n\nUUID: 12345778-1234-abcd-ef00-0123456789ac\n\nncacn_ip_tcp:192.168.0.242[49668]\n<\/pre>\n<p>The output from this command will have an almost overwhelming amount of output.\u00a0 Within this mountain of data will be just a handful of high-numbered ephemeral ports on which the server is listening.\u00a0 You are looking for any lines that have <strong><em>&#8220;ip_tcp&#8221;<\/em><\/strong> in them and the ports are in brackets at the end of the line (highlighted in blue above).\u00a0 This is where we will get a focused list of listening ports from the RPC server to query and validate connectivity. In the abbreviated example above, ports 49664 , 64555, 64502,and 49668 are listening.\u00a0 Note that 49668 is listed twice.\u00a0 There will be duplicates that you will have to filter out. Once you have the full (and de-duplicated) list put together, you can then feed that list of ports back into PORTQRY.EXE to validate that they are reachable over the network. About now, you are probably saying to yourself that&#8217;s a\u00a0 lot of work!\u00a0 Never fear, I didn&#8217;t do this too many times before I decided to automate it in PowerShell. (Editor.\u00a0 Queue up Mighty Mouse and &#8220;Here I come to save the DAY!&#8221;)<\/p>\n<h3>RPCCheckv2.ps1 to the rescue!<\/h3>\n<pre class=\"lang:ps decode:true\"># This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment.\n# THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\/OR\n# FITNESS FOR A PARTICULAR PURPOSE.\n#\n#\n# Script queries port 135 to get the listening ephemeral ports from the remote server\n#  and verifies that they are reachable.\n#\n#\n#  Usage:  RPCCheckv2 -Computer YourServerNameHere\n#\n#\n\n\n&lt;#PSScriptInfo\n\n.VERSION 1.1\n\n.GUID 2fda37e6-9d6d-4cff-b0ae-9f924ddf4afb\n\n.AUTHOR Ryan Ries\n\n.COMPANYNAME \n\n.COPYRIGHT \n\n.TAGS \n\n.LICENSEURI \n\n.PROJECTURI \n\n.ICONURI \n\n.EXTERNALMODULEDEPENDENCIES \n\n.REQUIREDSCRIPTS \n\n.EXTERNALSCRIPTDEPENDENCIES \n\n.RELEASENOTES\n\n\n#>\n\n&lt;# \n\n.DESCRIPTION \n This script tests TCP network connectivity to not just the RPC Endpoint Mapper on port 135, but it also checks TCP network connectivity to each of the registered endpoints returned by querying the EPM.  I wrote this because many firewall teams have a difficult time with RPC, and they will end up allowing the Endpoint Mapper on port 135, but forget to also allow the ephemeral ports through the firewall.  This script uses localhost by default, but obviously you can specify a remote machine name or IP address to test a server across the network.  The script works by P\/Invoking functions exported from rpcrt4.dll to get an enumeration of registered endpoints from the endpoint mapper, so it's not just a wrapper around portqry.exe.  \n\n Added dictionary for return since this script needs the port numbers returned - JV 10-31-2021\n#> \n\nParam(\n[string]$Computer\n)\n# Author: Ryan Ries [MSFT]\n# Origianl date: 15 Feb. 2014\n#Requires -Version 3\nFunction Test-RPC\n{\n    [CmdletBinding(SupportsShouldProcess=$True)]\n    Param([Parameter(ValueFromPipeline=$True)][String[]]$ComputerName = 'localhost')\n    BEGIN\n    {\n        Set-StrictMode -Version Latest\n        $PInvokeCode = @'\n        using System;\n        using System.Collections.Generic;\n        using System.Runtime.InteropServices;\n\n\n\n        public class Rpc\n        {\n            \/\/ I found this crud in RpcDce.h\n\n            [DllImport(\"Rpcrt4.dll\", CharSet = CharSet.Auto)]\n            public static extern int RpcBindingFromStringBinding(string StringBinding, out IntPtr Binding);\n\n            [DllImport(\"Rpcrt4.dll\")]\n            public static extern int RpcBindingFree(ref IntPtr Binding);\n\n            [DllImport(\"Rpcrt4.dll\", CharSet = CharSet.Auto)]\n            public static extern int RpcMgmtEpEltInqBegin(IntPtr EpBinding,\n                                                    int InquiryType, \/\/ 0x00000000 = RPC_C_EP_ALL_ELTS\n                                                    int IfId,\n                                                    int VersOption,\n                                                    string ObjectUuid,\n                                                    out IntPtr InquiryContext);\n\n            [DllImport(\"Rpcrt4.dll\", CharSet = CharSet.Auto)]\n            public static extern int RpcMgmtEpEltInqNext(IntPtr InquiryContext,\n                                                    out RPC_IF_ID IfId,\n                                                    out IntPtr Binding,\n                                                    out Guid ObjectUuid,\n                                                    out IntPtr Annotation);\n\n            [DllImport(\"Rpcrt4.dll\", CharSet = CharSet.Auto)]\n            public static extern int RpcBindingToStringBinding(IntPtr Binding, out IntPtr StringBinding);\n\n            public struct RPC_IF_ID\n            {\n                public Guid Uuid;\n                public ushort VersMajor;\n                public ushort VersMinor;\n            }\n\n\n            \/\/ Returns a dictionary of &lt;Uuid, port>\n            public static Dictionary&lt;int, string> QueryEPM(string host)\n            {\n                Dictionary&lt;int, string> ports_and_uuids = new Dictionary&lt;int, string>();\n                int retCode = 0; \/\/ RPC_S_OK \n                               \n                IntPtr bindingHandle = IntPtr.Zero;\n                IntPtr inquiryContext = IntPtr.Zero;                \n                IntPtr elementBindingHandle = IntPtr.Zero;\n                RPC_IF_ID elementIfId;\n                Guid elementUuid;\n                IntPtr elementAnnotation;\n\n                try\n                {                    \n                    retCode = RpcBindingFromStringBinding(\"ncacn_ip_tcp:\" + host, out bindingHandle);\n                    if (retCode != 0)\n                        throw new Exception(\"RpcBindingFromStringBinding: \" + retCode);\n\n                    retCode = RpcMgmtEpEltInqBegin(bindingHandle, 0, 0, 0, string.Empty, out inquiryContext);\n                    if (retCode != 0)\n                        throw new Exception(\"RpcMgmtEpEltInqBegin: \" + retCode);\n                    \n                    do\n                    {\n                        IntPtr bindString = IntPtr.Zero;\n                        retCode = RpcMgmtEpEltInqNext (inquiryContext, out elementIfId, out elementBindingHandle, out elementUuid, out elementAnnotation);\n                        if (retCode != 0)\n                            if (retCode == 1772)\n                                break;\n\n                        retCode = RpcBindingToStringBinding(elementBindingHandle, out bindString);\n                        if (retCode != 0)\n                            throw new Exception(\"RpcBindingToStringBinding: \" + retCode);\n                            \n                        string s = Marshal.PtrToStringAuto(bindString).Trim().ToLower();\n                        if(s.StartsWith(\"ncacn_ip_tcp:\"))\n                            if (ports_and_uuids.ContainsKey(int.Parse(s.Split('[')[1].Split(']')[0])) == false) ports_and_uuids.Add(int.Parse(s.Split('[')[1].Split(']')[0]), elementIfId.Uuid.ToString());\n                           \n                        RpcBindingFree(ref elementBindingHandle);\n                        \n                    }\n                    while (retCode != 1772); \/\/ RPC_X_NO_MORE_ENTRIES\n\n                }\n                catch(Exception ex)\n                {\n                    Console.WriteLine(ex);\n                    return ports_and_uuids;\n                }\n                finally\n                {\n                    RpcBindingFree(ref bindingHandle);\n                }\n                \n                return ports_and_uuids;\n            }\n        }\n'@\n    }\n    PROCESS\n    {\n \n        [Bool]$EPMOpen = $False\n        [Bool]$bolResult = $False\n        $Socket = New-Object Net.Sockets.TcpClient\n                \n        Try\n        {                    \n            $Socket.Connect($ComputerName, 135)\n            If ($Socket.Connected)\n            {\n                $EPMOpen = $True\n            }\n            $Socket.Close()                    \n        }\n        Catch\n        {\n            $Socket.Dispose()\n        }\n                \n        If ($EPMOpen)\n        {\n            Add-Type $PInvokeCode\n                    \n            # Dictionary &lt;Uuid, Port>\n            $RPC_ports_and_uuids = [Rpc]::QueryEPM($Computer)\n            $PortDeDup = ($RPC_ports_and_uuids.Keys) | Sort-Object -Unique\n            Foreach ($Port In $PortDeDup)\n            {\n                $Socket = New-Object Net.Sockets.TcpClient\n                Try\n                {\n                    $Socket.Connect($Computer, $Port)\n                    If ($Socket.Connected)\n                    {\n                        Write-Output \"$Port Reachable\"\n                    }\n                    $Socket.Close()\n                }\n                Catch\n                {\n                    Write-Output \"$Port Unreachable\"\n                    $Socket.Dispose()\n                }\n\n            }\n\n        }\n\n  \n    }\n\n    END\n    {\n\n    }\n}\n\nTest-RPC -ComputerName $Computer\n<\/pre>\n<p>Some things to note regarding the script: In testing, I found that there were cases where the Windows Firewall did not have default rules outside of the system-created rules for say, Active Directory or DFS. In my case, a handful of ports fell outside of those bounds and ironically this turned into a troubleshooting session to figure that out. To get to the point\u2026normal troubleshooting still applies, and you have to assess whether you want to make permanent rules in the firewall to allow traffic. In my case, put temporary rules in place to make sure that the blocks were removed for testing only and will now monitor the firewall logs to see if they need to be opened.<\/p>\n<p>Finally At the end of all of this, our family lion of a house cat (rescued from the Humane Society by the), Roger, was very impressed&#8230;you can just see it on his face. <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1.jpg\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1-300x300.jpg\" alt=\"Image 20160906 141752 2 300 215 300\" width=\"300\" height=\"300\" class=\"alignnone size-medium wp-image-87434\" srcset=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1.jpg 300w, https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1-150x150.jpg 150w, https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1-24x24.jpg 24w, https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1-48x48.jpg 48w, https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/11\/20160906_141752-2-300x300-1-96x96.jpg 96w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Ned, in the off chance that you read this, I&#8217;m a dog person all the way, but the daughter wanted a cat.\u00a0 If it helps, I asked for the &#8220;most dog-like&#8221; cat they had, and Roger doesn&#8217;t disappoint.<\/p>\n<p>So that is all there is to pinging available RPC ports with PowerShell!\u00a0<\/p>\n<p>Pop by next week as we delve into some amazing work with PowerShell and Parallel processes! I invite you to follow me on<\/p>\n<p><a href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x73;c&#114;&#105;&#x70;&#x74;&#101;&#114;&#x40;&#x6d;&#105;&#99;&#x72;&#x6f;s&#111;&#102;&#x74;&#x2e;&#99;&#111;&#x6d;\">&#x73;c&#114;&#105;&#x70;&#x74;&#101;&#114;&#x40;&#x6d;&#105;&#99;&#x72;&#x6f;s&#111;&#102;&#x74;&#x2e;&#99;&#111;&#x6d;<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Forum<\/a>. See you tomorrow. Until then, Keep on Scripting! <strong>Your good friend, Doctor Scripto<\/strong> PowerShell, Doctor Scripto, Sysinternals, Joel Vickery, RPC, Ping<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Using PowerShell to identify RPC ports in use by capturing content from PowerShell We&#8217;d like to introduce you today to one of our newest bloggers!\u00a0 It&#8217;s a froopingly awesome friend of ours, Joel Vickery, PFE.\u00a0 (did I mention Dr. Scripto is a big fan of books written by Douglas Adams?&#8230;.oops!) Take it away Joel! [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1739,1738,685,688],"tags":[1740,2740,377,2741,1968],"class_list":["post-86613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-doctor-scripto","category-powershell","category-scripting-techniques","category-text-manipulation","tag-doctor-scripto","tag-joel-vickery","tag-powershell","tag-rpc","tag-sysinternals"],"acf":[],"blog_post_summary":"<p>Summary: Using PowerShell to identify RPC ports in use by capturing content from PowerShell We&#8217;d like to introduce you today to one of our newest bloggers!\u00a0 It&#8217;s a froopingly awesome friend of ours, Joel Vickery, PFE.\u00a0 (did I mention Dr. Scripto is a big fan of books written by Douglas Adams?&#8230;.oops!) Take it away Joel! [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/86613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=86613"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/86613\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=86613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=86613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=86613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}