How to verify VMware HCX firewall access rules

Problem Statement

As many of you know that I have recently joined the Oracle Cloud team as a Master Principal Cloud Architect. A part of my new role is helping the customers move their workloads to the Oracle Cloud VMware solution (OCVS). If you are not familiar with OCVS, I would recommend reading through this link. VMware HCX is the solution of choice for moving the workloads. I found that most of the HCX deployments on ‘on-premises’ fail because customers drop adding the required firewall rules. We spend hours troubleshooting HCX issues that mostly end up being blocked ports. The automation engineer in me was keen on solving this problem.

Solution

I decided to do a quick and easy script in Python to verify all the ports. I had never scripted in Python before, so I thought it was a good opportunity to learn some python as well. Here’s a list of ports, that a cloud engineer or a customer has to manually verify to get the VMware HCX working. As you can see the list is HUGE!

HCX Firewall Rules

Python

I used the native Python sockets to check the TCP and UDP connections required. Firewall ports in my script are hard-coded. You can run this script in an interactive way or in an expert mode by updating the IP’s in the script. This can be used by any hypersclaers for the HCX setup/troubleshooting.

# ================================================================================================
#
# Function:  Test TCP and UDP Port connectivity
#
# Description: Test the TCP and UDP ports required for the HCX connection.
#
# Developer: Barjinder Singh (mail.barjinder@gmail.com)
# ================================================================================================
 
import socket
import subprocess
import sys
from datetime import datetime
 
# Clear the screen
tmp = subprocess.call('clear', shell=True)
tmp = subprocess.call('cls', shell=True)
 
# Check what time the script started
t1 = datetime.now()
 
# Print banner with information on which host we are about to scan
print ("-" * 60)
print ("Oracle Services - checking ports for HCX connectivity")
print ("-" * 60)
 
interactivemode = input ("Interactive mode 'yes' or 'no': ")
 
if interactivemode == "yes" or interactivemode == "YES":
    hcxmanager = input("Enter the IP Address of the OCVS HCX Cloud Manager: ")
    hcxIX = input("Enter the IP Address of the OCVS HCX Cloud Interconnect Appliance (IX): ")
    nsxt = input("Enter the IP Address of the OCVS NSX-T Manager: ")
    cloudvc = input("Enter the IP Address of the OCVS vCenter Server: ")
    onpremVC = input("Enter the IP Address of the On-Premises vCenter Server: ")
    onpremESXi = input("Enter comma-seperated list of the On-Premises ESXi Servers: ")
    onpremDNS = input("Enter the IP Address of the On-Premises DNS Server: ")
    ntpServer = input("Enter the IP Address of the On-Premises NTP Server: ")
    syslogServer = input("Enter the IP Address of the On-Premises syslog Server[Optional]: ")
 
 
#Replaces the IP's with the values provided by the customer.
if interactivemode == "no"  or interactivemode == "NO":
    hcxmanager = "x.x.x.x"  #Enter the IP Address of the OCVS HCX Cloud Manager
    nsxt = "x.x.x.x" #Enter the IP Address of the OCVS NSX-T Manager
    cloudvc = "x.x.x.x" #Enter the IP Address of the OCVS vCenter Server
    onpremVC = "x.x.x.x" #Enter the IP Address of the On-Premises vCenter Server
    onpremESXi = ("x.x.x.x", "x.x.x.x", "x.x.x.x" ) #Enter a comma-seperated list of the On-Premises ESXi Servers
    onpremDNS = ("x.x.x.x", "x.x.x.x") #Enter the IP Address of the On-Premises DNS Server
    ntpServer = "x.x.x.x" #Enter the IP Address of the On-Premises NTP Server
    syslogServer = "x.x.x.x"
    hcxIX = "x.x.x.x"   #Enter the IP Address of the OCVS HCX Cloud Interconnect Appliance (IX)
 
 
def colored(r, g, b, text):
    return "\033[38;2;{};{};{}m{} \033[38;2;255;255;255m".format(r, g, b, text)
 
#Function to test TCP ports
def tcp_port_check(HOST,PORT):
    print ("-" * 60)
    print  ("\033[1;33mTesting TCP port connectivity --> "+ HOST + ":"+ PORT )
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        s.connect((HOST,int(PORT)))
        print  (colored(0,255,0,("Result : TCP Port " + PORT+  " is open")))
        s.settimeout(2)
        s.shutdown(2)
        return True
    except:
        print  (colored(255,0,0,("Result : TCP Port " + PORT+" is not open. Check the firewall for blocked ports.")))
        return False
        s.close()
 
#Function to test UDP ports
def udp_port_check(HOST,PORT):
    print ("-" * 60)
    print  ("\033[1;33mTesting UDP port connectivity --> "+ HOST + ":"+ str(PORT) )
    # Create a UDP socket at client side
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        result = sock.connect_ex((HOST, PORT))
        if result == 0:
            print (colored(0,255,0,("Result : UDP Port {} is Open".format(PORT))))
            return True
        sock.close()
 
    except KeyboardInterrupt:
        print ("You pressed Ctrl+C")
        sys.exit()
 
    except socket.error:
        print (colored(255,0,0,(("Result : UDP Port " + str(PORT)+" is not open. Check the firewall for blocked ports."))))
 
# VMware SaaS gateway connectivity check  
print ("-" * 60)
print ("Please wait, checking SaaS gateway connectivity")
print ("-" * 60)
#SaaS gateway connectivity
tcp_port_check("connect.hcx.vmware.com","443")
tcp_port_check("hybridity-depot.vmware.com","443")
 
 #HCX manager in cloud connectivity check
print ("-" * 60)
print ("Please wait, checking OCVS connectivity")
print ("-" * 60)
# OCVS connectivity
if hcxmanager:
    tcp_port_check(hcxmanager,"443")
else:
    print (colored(255,0,0,("Invalid HCX Manager IP")))
 
if nsxt:
    tcp_port_check(nsxt,"443")
else:
    print (colored(255,0,0,("Invalid NSXT Manager IP")))
 
if cloudvc:
    tcp_port_check(cloudvc,"443")
else:
     print (colored(255,0,0,("Invalid OCVS VC IP")))
 
 
#On-Prem connectivity
 
#ESXi hosts
print ("-" * 60)
print ("Please wait, checking On-Premises ESXi connectivity")
print ("-" * 60)
if onpremESXi:
    for i in onpremESXi:
        tcp_port_check(i,"443")
        tcp_port_check(i,"902")
        tcp_port_check(i,"80")
else:
    print (colored(255,0,0,("Invalid On-Prem ESXi IPs")))
 
 
# DNS Servers
print ("-" * 60)
print ("Please wait, checking On-Premises DNS connectivity")
print ("-" * 60)
if onpremDNS:
    for j in onpremDNS:
        tcp_port_check(j,"53")
else:
    print (colored(255,0,0,("Invalid On-Prem DNS IPs")))
 
# On-Prem VC
print ("-" * 60)
print ("Please wait, checking On-Premises VC connectivity")
print ("-" * 60)
if onpremVC:
    tcp_port_check(onpremVC,"443")
else:
    print (colored(255,0,0,("Invalid On-Prem VC IP")))
 
#On-Prem Syslog
if syslogServer:
    print ("-" * 60)
    print ("Please wait, checking On-Premises VC connectivity")
    print ("-" * 60)
    tcp_port_check(syslogServer,"514")
 
 
# UDP connectivity
print ("-" * 60)
print ("Please wait, checking UDP connectivity")
print ("-" * 60)
udp_port_check(hcxIX,4500)
 
# Checking the time again
t2 = datetime.now()
 
# Calculates the difference of time, to see how long it took to run the script
total =  t2 - t1
 
# Printing the information to screen
print ('Port Testing  Completed in: ', total)

Execution Instructions

The script needs to be run from the HCX Connector (HCX Manager On-Prem).

1. SSH to the HCX On-Prem HCX Manager (connector) as admin.

2. SU –
3. cd /tmp
4. vi portchecket.py

5. Paste the script in this file, save and close (wq!)
6. Execute the script by typing “python3 portcheck.py

The script will output if the required ports are blocked or not. Without all the firewall rules open, HCX will not work and the error messages can be misleading at times. Even though HCX has a built-in diagnosis feature and is extensive but this script is a targetted approach just for the firewall rules.

Conclusion

The script is a general port checker python and can be extended to use between any TCP/UDP links. The script can be updated to automatically get the ESXi IP’s etc. However, I have not added that feature as it would involve installing binaries on the execution machine and not all customers are comfortable installing those, so I have kept it simple. It doesn’t cover all the firewall rules required for the working setup but covers a majority of required ports.

Happy reading!

Leave a Reply