I love Citrix, I really do, but I hate their documentation. Its too static with very little explanation on top of being always missing some part of the configuration or prerequisites. Compared to other vendors and on a scale of 1 to 10, I would give them a 6 for documentation and to a vendor that is suppose to be leading End User Computing that is not acceptable ( Changing the documentation interface does not count )…
Update: Multi NIC Multi IP is now officially supported by Microsoft and Citrix. https://vzerotohero.com/2017/03/step-by-step-configuring-multiple-ip-addresses-for-netscaler-vpx-nic-on-microsoft-azure-arm/
We have a customer looking to deploy Citrix NetScaler on the cloud “Microsoft Azure” to load balance and protect “WAF” about 10 applications hosted on-premise and as IaaS machines on azure. Citrix NetScaler as of now works in single IP mode on Azure which means we can have only one IP on NetScaler VPX which would be used for management and other services. The challenge here is that we can only publish one port per IP so unless all applications have different ports “ Never the case with web applications “ we wouldn’t be able for instance to publish two web servers on port 80 or 443 because they would be using the same port.
Now with NetScaler on Azure, port 443 cannot be used anyhow nor port 80 because they are reserved internally by NetScaler considered as private ports ( https://docs.citrix.com/en-us/netscaler/11/getting-started-with-vpx/deploy-vpx-on-azure.html ) so in order to publish 80 or 443 which are the most well known ports out there, we need to either use Azure NSG (Network Security Group) which to some extent a layer 4 stateless firewall with Nating capabilities and NAT 443 or 80 to the internal port that our service will run on NetScaler would be using. NSG is fine if you have one NetScaler but if you want to have a highly available NetScaler on Azure then you need to use Azure Load balancer. If you are using NetScaler with Single IP mode and active/standby HA on azure then make sure when configuring the HA to select the INC option IF the two Netscalers are on different subnets.
Configure Active-Active NetScaler load balancing on Azure Resource Manager
You might be thinking OK there exists a workaround for this limitation. I can create multiple load balancers with different public IPs and point them to the same NetScaler IP which would be hosting a service on different ports thus I can create for example 3 load balancers with 3 public IPs and connect them to the single VIP NetScaler which have different internal load balancing or Access Gateway virtual server ports still on the same NS single IP. Nop it wont work at least as of now because with Azure Load Balancer a single NIC which is connected to any VM can only be part of One load balancer although the Idea sounds great and technically should be feasible except that’s what Azure currently has. On a side note Azure ARM recently released single NIC support multiple private & public IPs for VMs in preview mode but I have no idea if its possible to implement this on NetScaler VM since its not an ordinary Linux VM, It would be nice if someone has a go at it.
Citrix NetScaler HA on Microsoft Azure “ The Multi NIC/IP Untold Truth ’’
Now the solution to overcome this limitation is by creating multiple Azure public cloud IP addresses and from within the same load balancer we can direct traffic to the NetScaler VPX which will still have a single IP with each service having different port. To make it as clear as possible, NetScaler will still have one IP, each service on NetScaler ( LB or AG or CS) will have that same on IP but with different ports, Azure load balancer would have public IPs one for each service and this same load balancer can create different load balancing rules specifying that this public IP would go to this port and the same goes for other services each public azure IP would be bound to that port. Citrix documentation gives the following graphical representation so hope by now it all makes sense, btw VIP is not the NetScaler VIP we are familiar with but it just means Azure Public IP while the VPX IP is actually same IP for all services while the port is different so the load balancing rules are bound to the port eventually not the IP since it is single.
Unfortunately this configuration cannot be done in full through Microsoft Azure GUI but fear not as I am going to make it as simple as possible, just copy and paste with changing the required names and you will be fine. We can see that some configuration parameters are a must with PowerShell so for the sake of this post, we are going to do the whole thing using PowerShell from the ground up.
1- Download Microsoft Web Platform Installer package from http://go.microsoft.com/fwlink/p/?linkid=320376&clcid=0x409 and Install Azure PowerShell module.
2- Open PowerShell ISE and type “ Add-AzureRmAccount “ . Login to your account and make sure the account is added properly.The –SubscriptionId and –SubscriptionName can be used if you have different subscriptions.
3- Create a resource group. Change the names as per your requirements. I like to open a new ps1 in ISE for each set of commands as it makes it easy to troubleshoot so feel free to do so. Run by pressing the green play button.
$rgName = “NS”
$locName = “Central US”
New-AzureRmResourceGroup -Name $rgName -Location $locName
4- Create Storage Account.
New-AzureRmStorageAccount -Name $saName -ResourceGroupName $rgName -Type $saType -Location $locName
5- Create Availability Set.
New-AzureRmAvailabilitySet -Name $avName -ResourceGroupName $rgName -Location $locName
6- Create a Virtual Network with frontend and backend subnets. The NetScaler VPX will have an IP from the frontend subnet while the backend subnet is used between the load balancer and NetScaler. Change the subnets to fit your requirements.
$vnetName = “diyarLBVnet”
$frontendSubnet=New-AzureRmVirtualNetworkSubnetConfig -Name frontendSubnet -AddressPrefix 192.168.4.0/24
$backendSubnet=New-AzureRmVirtualNetworkSubnetConfig -Name backendSubnet -AddressPrefix 192.168.5.0/24
New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $locName -AddressPrefix 192.168.0.0/16 -Subnet $frontendSubnet,$backendSubnet
7- Create the Public IPs required, create more IPs depending on how many applications with same port the NetScaler is going to host. Make sure to change the DnsName of each public IP ( this is just the azure DnsName so it wont effect anything just make it unique as later on you will create your own DNS records on your public domain and point your users to those DNS hostnames to access whatever application is being published).
$publicIP1 = New-AzureRmPublicIpAddress -Name $pubName1 -ResourceGroupName $rgName -Location $locName -AllocationMethod Static -DomainNameLabel $dnsName1
$publicIP2 = New-AzureRmPublicIpAddress -Name $pubName2 -ResourceGroupName $rgName -Location $locName -AllocationMethod Static -DomainNameLabel $dnsName2
8- Create Load balancer front end IPs which will be linked to the public IPs created earlier.
$frontendIP1 = New-AzureRmLoadBalancerFrontendIpConfig -Name $FIPName1 -PublicIpAddress $publicIP1
$frontendIP2 = New-AzureRmLoadBalancerFrontendIpConfig -Name $FIPName2 -PublicIpAddress $publicIP2
9- Create Load balancer backend pool which will be linked to the NetScaler VPX.
$BEPool1 = “backend-Pool1”
$beaddresspool1= New-AzureRmLoadBalancerBackendAddressPoolConfig -Name $BEPool1
10- Create Load Balancer health probe which would check if NetScaler is operatinal and failover accordingly if an HA NS is implemented. port 9000 is a private NetScaler port and it is recommended by Citrix to use that port for probing.
$healthProbe = New-AzureRmLoadBalancerProbeConfig -Name HealthProbe -Protocol Tcp -Port 9000 -IntervalInSeconds 5 -ProbeCount 2
11- Create Load balancing rules which state what port is being published to the internet and what port is being communicated with internally with the applications hosted on NetScaler. In the below example we are publishing port 80 to the outside world so users hit the public IP1:80 and then are redirected to the virtual server on NetScaler which is using port 10080. The second public IP has the same concept but redirecting to virtual server with port 10081. You can use any port for publishing. Each public IP has to have a rule to talk back to NetScaler so if you are creating more than 2 IPs , make sure to do the same and put the correct internal port hosted on NS for the service published. The third rule lbrule3 is used to access management GUI interface on NetScaler using public port 10080 so to initially configure NetScaler you would connect to public IP1:10080 or you can use any other port for that matter except the one you are using for other services. The NAT rule is a direct SSH port 22 NAT to NetScaler so that it is accessible via putty,
$lbrule1 = New-AzureRmLoadBalancerRuleConfig -Name “HTTP1” -FrontendIpConfiguration $frontendIP1 -BackendAddressPool $beAddressPool1 -Probe $healthProbe -Protocol Tcp -FrontendPort 80 -BackendPort 10080
$lbrule2 = New-AzureRmLoadBalancerRuleConfig -Name “HTTP2” -FrontendIpConfiguration $frontendIP2 -BackendAddressPool $beAddressPool1 -Probe $healthProbe -Protocol Tcp -FrontendPort 80 -BackendPort 10081
$lbrule3 = New-AzureRmLoadBalancerRuleConfig -Name “HTTPNS” -FrontendIpConfiguration $frontendIP1 -BackendAddressPool $beAddressPool1 -Probe $healthProbe -Protocol Tcp -FrontendPort 10080 -BackendPort 80
$inboundNATRule1= New-AzureRmLoadBalancerInboundNatRuleConfig -Name SSH1 -FrontendIpConfiguration $frontendIP1 -Protocol TCP -FrontendPort 22 -BackendPort 22
12- Now the actual creation of the Load balancer with all perimeters created earlier.
$lbName = “NSALB”
$NRPLB = New-AzureRmLoadBalancer -ResourceGroupName $rgName -Name $lbName -Location $locName -InboundNatRule $inboundNATRule1 -FrontendIpConfiguration $frontendIP1, $frontendIP2 -LoadBalancingRule $lbrule1, $lbrule2, $lbrule3 -BackendAddressPool $beAddressPool1 -Probe $healthProbe
13- Create the NIC which will be attached to the NetScaler that we are going to create next making sure it is linked to all subnets created earlier. ( here is where Citrix documentation forgot to set the $vnet variable so received a couple of cannot set null index value errors until I added it ).
$VNET = Get-AzureRmVirtualNetwork -ResourceGroupName $rgName -Name $vnetName
$lb=Get-AzureRmLoadBalancer -Name $lbName -ResourceGroupName $rgName
$nic1=New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName -Location $locName -Subnet $vnet.Subnets[$subnetIndex] -LoadBalancerBackendAddressPool $lb.BackendAddressPools[$bePoolIndex] -LoadBalancerInboundNatRule $lb.InboundNatRules[$natRuleIndex]
14- Create the NetScaler VPX using earlier created variables.
$skuName = “netscalerbyol”
$avSet=Get-AzureRmAvailabilitySet -Name $avName -ResourceGroupName $rgName
$vm1=New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $avset.Id
$cred=Get-Credential -Message “Type Credentials which will be used to login to VPX instance”
$vm1=Set-AzureRmVMOperatingSystem -VM $vm1 -Linux -ComputerName $vmName -Credential $cred -Verbose
$vm1=Set-AzureRmVMSourceImage -VM $vm1 -PublisherName $pubName -Offer $offerName -Skus $skuName -Version “latest”
$vm1=Add-AzureRmVMNetworkInterface -VM $vm1 -Id $nic1.Id
$storageAcc=Get-AzureRmStorageAccount -ResourceGroupName $rgName -Name $saName
$osDiskUri1=$storageAcc.PrimaryEndpoints.Blob.ToString() + “vhds1/” + $diskName + “.vhd”
$vm1=Set-AzureRmVMOSDisk -VM $vm1 -Name $diskName -VhdUri $osDiskUri1 -CreateOption fromImage
Set-AzureRmVMPlan -VM $vm1 -Publisher $pubName -Product $offerName -Name $skuName
New-AzureRmVM -ResourceGroupName $rgName -Location $locName -VM $vm1
15- Verify everything has been created inside Azure ARM Portal resource group created for this deployment.
17- For testing purposes I have created 2 access gateways with the same ports that have been configured previously but I have changed the internal load balancing port from 80 which we created using PowerShell to 443 since Gateway requires SSL using Azure Load balancer GUI Load balancing rules.
18- Each of these access gateways is accessible from the public Azure IP assigned to it which is visible from the Azure load balancer rules. Again it is redirecting based on port so I hope you got the concept by now . The public IP will forward to the same NetScaler IP which it is talking to privately on different port for each service.
19- Are the Access Gateway pages accessible !? Lets try to access both public IPs on port 443 and see …
20- For a highly available deployment with multiple IP addresses , all the procedures are exactly the same except that we have to create a second NIC and bind it to the second NetScaler created then add that NetScaler to the availability group. Same commands apply for the new NIC and new NetScaler, just change the 2nd NIC name and 2nd NetScaler name.