You have created a Linux VM in Azure. The next thing you’ll do is configure it for the tasks we want to move to Azure.
Unless you’ve set up a site-to-site VPN to Azure, your Azure VMs won’t be accessible from your local network. If you’re just getting started with Azure, it’s unlikely that you have a working site-to-site VPN. So how can you connect to the virtual machine?
Azure VM IP addresses
As we saw a moment ago, Azure VMs communicate on a virtual network. They can also have an optional public IP address assigned to them. With a public IP, we can interact with the VM over the Internet. Alternatively, we can set up a virtual private network (VPN) that connects our on-premises network to Azure – letting us securely connect to the VM without exposing a public IP.
Public IP addresses in Azure are dynamically allocated by default. That means the IP address can change over time – for VMs the IP address assignment happens when the VM is restarted. You can pay more to assign static addresses, if you want to connect directly to an IP address and need to ensure that the IP address will not change.
Acknowledging these restrictions, and the alternatives described above, we will use the public IP address of the VM in this training.
Connecting to the VM with SSH
To connect to the VM via SSH, you need:
- the public IP address of the VM
- the username of the local account on the VM
- a public key configured in that account
- access to the corresponding private key
- port 22 open on the VM
Previously, you generated an SSH key pair, and added the public key to the VM configuration, and ensured that port 22 was open.
Connect to a Linux virtual machine with SSH
Let’s connect to our Linux VM with SSH, and configure Apache, so we have a running web server.
Get the public IP address of the VM
- In the Azure portal , ensure the Overview panel for the virtual machine that you created earlier is open. You can find the VM under All Resources if you need to open it. The overview panel allows you to:
- See if the VM is running
- Stop or restart the VM
- Get the public IP address of the VM
- See the activity of the CPU, disk, and network
- Click the Connect button at the top of the pane.
- In the Connect to virtual machine panel, note the IP address and Port number settings. On the SSH tab, you will also find the command you need to execute locally to connect to the VM. Copy the command to the clipboard.
Connect with SSH
- Paste the command from your clipboard into the Azure Cloud Shell. It should look something like the sample below; however, it will have a different IP address (and perhaps a different username if you didn’t use jim!):
ssh [email protected]
The first time we connect, SSH will ask us about authenticating against an unknown host. SSH is telling you that you’ve never connected to this server before. If that’s true, then it’s perfectly normal, and you can respond with yes to save the fingerprint of the server in the known host file:
The authenticity of host '137.117.101.249 (137.117.101.249)' can't be established. ECDSA key fingerprint is SHA256:w1h08h4ie1iMq7ibIVSQM/PhcXFV7O7EEhjEqhPYMWY. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '137.117.101.249' (ECDSA) to the list of known hosts.
- This command will open an SSH connection and place you at a shell command prompt for Linux.
- Try executing a few Linux commands
ls -la /
to show the root of the diskps -l
to show all the running processesdmesg
to list all the kernel messageslsblk
to list all the block devices – here you will see your drives
The more interesting thing to observe in the list of drives is what is missing. Notice that our Data drive (
sdc
) is present but not mounted into the file system. Azure added a VHD but didn’t initialize it.
Initialize data disks
Any additional drives you create from scratch need to be initialized and formatted. The process for initializing is identical to a physical disk:
- First, identify the disk. We did that above. You could also use
dmesg | grep SCSI
, which will list all the messages from the kernel for SCSI devices. - Once you know the drive (
sdc
) you need to initialize, you can usefdisk
to do that. You will need to run the command withsudo
and supply the disk you want to partition. We can use the following command to create a new primary partition:(echo n; echo p; echo 1; echo ; echo ; echo w) | sudo fdisk /dev/sdc
- Next, we need to write a file system to the partition with the
mkfs
command.sudo mkfs -t ext4 /dev/sdc1
- Finally, we need to mount the drive to the file system. Let’s assume we will have a
data
folder. Let’s create the mount point folder and mount the drive.sudo mkdir /data && sudo mount /dev/sdc1 /data
We initialized the disk and mounted it. If you are interested in more details on this process go through the Add and size disks in Azure virtual machines module. This task is covered in more detail there.
Install software onto the VM
As you can see, SSH allows you to work with the Linux VM just like a local computer. You can administer this VM as you would any other Linux computer: installing software, configuring roles, adjusting features, and other everyday tasks. Let’s focus on installing software for a moment.
You can also install software from the internet when you are connected to the VM via SSH. Azure machines are, by default, internet connected. You can use standard commands to install popular software packages directly from standard repositories. Let’s use this approach to install Apache.
Install the Apache web server
Apache is available within Ubuntu’s default software repositories, so we will install it using conventional package management tools:
- Start by updating the local package index to reflect the latest upstream changes:
sudo apt-get update
- Next, install Apache:
sudo apt-get install apache2 -y
- It should start automatically – we can check the status using
systemctl
:sudo systemctl status apache2 --no-pager
The
systemctl
command returns something like:apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Drop-In: /lib/systemd/system/apache2.service.d └─apache2-systemd.conf Active: active (running) since Mon 2018-09-03 21:00:03 UTC; 1min 34s ago Main PID: 11156 (apache2) Tasks: 55 (limit: 4915) CGroup: /system.slice/apache2.service ├─11156 /usr/sbin/apache2 -k start ├─11158 /usr/sbin/apache2 -k start └─11159 /usr/sbin/apache2 -k start test-web-eus-vm1 systemd[1]: Starting The Apache HTTP Server... test-web-eus-vm1 apachectl[11129]: AH00558: apache2: Could not reliably determine the server's fully qua test-web-eus-vm1 systemd[1]: Started The Apache HTTP Server.
It’s trivial to execute commands like this, however it’s a manual process – if we always need to install some software, you might consider automating the process using scripting. - Finally, we can try retrieving the default page through the public IP address. However, even though the web server is running on the VM, you won’t get a valid connection or response. Do you know why?
We need to perform one more step to be able to interact with the web server. Our virtual network is blocking the inbound request. We can change that through configuration. Let’s look at allowing the inbound request next.
Network and security settings
Making adjustments to server configuration is commonly performed with equipment in your on-premises environment. In this sense, you can consider Azure VMs to be an extension of that environment. You can alter configuration, manage networks, open or block traffic, and more through the Azure portal, the Azure CLI, or Azure PowerShell tools.
We’ve got our server running, and Apache is installed and serving up pages. Our security team mandates that we lock down all our servers, and we’ve not done anything to this VM yet. We didn’t do anything, and it let Apache listen on port 80. Let’s explore the Azure network configuration to see how to use the built-in security support to harden our server.
Opening ports in Azure VMs
By default, new VMs are locked down.
Apps can make outgoing requests, but the only inbound traffic allowed is from the virtual network (e.g., other resources on the same local network) and from Azure Load Balancer (probe checks).
There are two steps to adjusting the configuration to support different protocols on the network. When you create a new VM, you have an opportunity to open a few common ports (RDP, HTTP, HTTPS, and SSH). However, if you require other changes to the firewall, you will need to adjust them manually.
The process for this involves two steps:
- Create a network security group.
- Create an inbound rule allowing traffic on the ports you need.
What is a network security group?
Virtual networks (VNets) are the foundation of the Azure networking model and provide isolation and protection. Network security groups (NSGs) are the primary tool you use to enforce and control network traffic rules at the networking level. NSGs are an optional security layer that provides a software firewall by filtering inbound and outbound traffic on the VNet.
Security groups can be associated to a network interface (for per host rules), a subnet in the virtual network (to apply to multiple resources), or both levels.
Security group rules
NSGs use rules to allow or deny traffic moving through the network. Each rule identifies the source and destination address (or range), protocol, port (or range), direction (inbound or outbound), a numeric priority, and whether to allow or deny the traffic that matches the rule.
Each security group has a set of default security rules to apply the default network rules described above. These default rules cannot be modified but can be overridden.
How Azure uses network rules
For inbound traffic, Azure processes the security group associated to the subnet and then the security group applied to the network interface. Outbound traffic is handled in the opposite order (the network interface first, followed by the subnet).
The rules are evaluated in priority order, starting with the lowest priority rule. Deny rules always stop the evaluation. For example, if a network interface rule blocks an outbound request, any rules applied to the subnet will not be checked. For traffic to be allowed through the security group, it must pass through all applied groups.
The last rule is always a Deny All rule. This is a default rule added to every security group for both inbound and outbound traffic with a priority of 65500. That means to have traffic pass through the security group, you must have an allow rule, or the final default rule will block it.
Creating network security groups
Security groups are managed resources like most everything in Azure. You can create them in the Azure portal or through command-line scripting tools. The challenge is in defining the rules. Let’s look at defining a new rule to allow HTTP access and block everything else.
When we created the virtual machine (VM), we selected the inbound port SSH so we could connect to the VM. This created an NSG that’s attached to the network interface of the VM. That NSG is blocking HTTP traffic. Let’s update this NSG to allow inbound HTTP traffic on port 80.
Update the NSG on the network interface
Port 80 is open on the NSG applied to the subnet. But port 80 is blocked by the NSG applied to the network interface. Let’s fix that so we can connect to the website.
- Switch back to the Overview panel for the virtual machine. You can find the VM under All Resources.
- In the Settings section, select the Networking item.
- You should see the NSG rules for the subnet in the top section and the NSG rules for the network interface in the bottom section of the same tab. In the bottom section, for the NSG rules for the network interface, select Add inbound port rule.
- Switch to the Basic mode.
- Add the information for our HTTP rule:
- Set the Service to be HTTP. This sets up your port range.
- Set the Priority to 310.
- Give the rule a name; use allow-http-traffic.
- Give the rule a description.
- Click Add to create the rule.
Open the default webpage
Use the IP address of the server to make an HTTP request. It should now work.
One more thing
Always make sure to lock down ports used for administrative access. An even better approach is to create a VPN to link the virtual network to your private network and only allow RDP or SSH requests from that address range. You can also change the port used by SSH to be something other than the default. Keep in mind that changing ports is not sufficient to stop attacks. It simply makes it a little harder to discover.