As more organizations migrate business-critical workloads to the Azure cloud platform (or build new ones), they rely on applications and services being able to communicate with each other securely to provide services to their internal teams, business partners, and customers. Azure Virtual Network (VNet) is the core service for implementing secure private networking in Azure. A VNet is a virtual version of a physical network, implemented on the Azure cloud platform.
In this chapter, we will focus on the foundational concepts of implementing private network connectivity in Azure. We will walk through what Azure VNet is, its capabilities, the key differences between Azure VNet and a traditional on-premises network, and supported services that can be launched into Azure VNet (spoiler: as well as a virtual machine (VM), we can also deploy 20 other services into Azure VNet).
We’ll then go on to discuss key implementation options such as designing/assigning IP address spaces, segmentation using subnets, and resource IP address assignments – how resources are allocated an IP address (another spoiler: you can’t use self-managed DHCP!).
Lastly, we’ll talk about the routing and traffic flow functionalities of Azure VNet. In other words, how does routing work and how do we control traffic flow?
In this chapter, we will cover the following topics:
Each topic has been structured to align with the recommended network connectivity best practices in Azure. Let us get into this!
To follow along with the instructions in this chapter, you will need the following:
Before we proceed to cover the security best practices, let us prepare our Azure subscription for the hands-on exercises that we will complete later in the chapter.
Before we get too far into Azure networking concepts, let’s establish what Azure VNet is and the capabilities that it provides.
A VNet is a virtual version of a physical network, implemented on the Azure cloud platform. The main advantage that it has over a traditional network is that we don’t need to implement or maintain the underlying physical hardware for this network (these responsibilities are offloaded to our cloud provider – Microsoft). But for the most part, we can achieve similar capabilities and architectures that we can achieve on-premises. We can even implement more flexible architectures with Azure VNets due to the software-defined nature.
So, what capabilities does Azure VNet provide? Here is a short list of some use cases:
Limitation
An Azure subscription can have up to 1,000 VNets as of the time of writing (April, 2022). An additional subscription will be needed to grow beyond this limit.
Even though Azure VNet is similar to a traditional on-premises network in many ways, there are still important differences, mainly due to restrictions that have been put in place by Microsoft to ensure security in a multi-tenant platform such as Azure. Here are some key ones:
arp -a
command on a VM that is deployed in Azure VNet. You will notice that the MAC address resolution for VMs in the same subnet results in the same 12:34:56:78:9a:bc
value. This is because we are on a shared platform and the VNet is a Layer-3 overlay instead of Layer-2:Figure 1.1 – ARP table on an Azure VM
65330
, IP-in-IP encapsulated packets, and Generic Routing Encapsulation (GRE) packets are not allowed in Azure VNet. Any application or service capability that requires these protocols or communication types will need to be refactored before deployment into Azure VNet for it to work. The only protocols that are allowed are TCP, UDP, ICMP, and Unicast communication (except source port UDP/68 /
, destination port UDP/67
, and UDP source port 65330
, which is reserved for the host).Note
For more information on the differences of Azure VNet and traditional networks, refer to the document at https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-faq.
Now that you have some fundamental information on what Azure VNet is, let’s discuss how you would go about planning one, starting with considerations around naming it.
All Azure resources have a name that must be unique within a scope. The scope is different for each resource type. When creating a Vnet, its name must be unique within the scope of the resource group. This means that it is possible to have two Vnets in your Azure subscription with the same name as long as they don’t belong to the same resource group! This can be useful in a design that involves having the same Vnet resource name for both development and production environments, as shown in Figure 1.2.
Figure 1.2 – Vnet names must be unique for the resource group scope
Even though it is possible to have duplicate names within a subscription, it is not a recommended practice as it could later lead to confusion when investigating security incidents using logging information (we will cover network logging and monitoring later in this book). When investigating security incidents, it helps to be able to quickly identify affected resources and having a unique resource naming strategy for your Vnets helps with this.
Regarding naming best practices, it is best to define a naming convention as early as possible. This convention should be communicated to the teams with permission to create network resources in Azure, and preferably, the naming convention should be enforced using tools such as Azure Policy. To define a good naming strategy, consider these recommendations:
prod-eastus-webservices-Vnet
(Figure 1.3).Figure 1.3 – Sample Vnet naming convention
For more thoughts on naming conventions, please refer to this document: https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming.
Almost all Azure services are created in a regional location specified at creation time. I said almost all because there are some exceptions – so-called global or non-regional services that are not pinned to a region. Azure Vnet is a regional service.
As of the time of writing (April 2022), the Azure cloud has 55 active regions in which we can create Vnets (with nineteen announced regions coming soon).
So, which regions should you select when creating Vnets? Consider the following three points to guide your decision regarding this:
The following diagram shows an example of a Vnet with AZs:
Figure 1.4 – A Vnet with AZs
Also, keep in mind that the decision to distribute your network workloads in multiple AZs in a region results in an extra cost of 0.01 USD (0.008 GBP) per gigabyte of data transferred between AZs for both inbound and outbound traffic.
Every Vnet must have at least one IP address space assignment. A Vnet space assignment can either be single-stack (IPv4 address space only) or dual-stack (IPv4 and IPv6 address spaces). At the time of writing, an IPv6-only Vnet is not supported! You might be able to create an IPv6-only Vnet in the portal, but you will not be able to attach a virtual network interface card (NIC) to it. Attempting it will result in the error message shown in Figure 1.5:
Figure 1.5 – Your Vnet must have at least one IPv4 address space to use IPv6
Note
Azure does not yet support an IPv6-only Vnet and subnet, but you can implement dual-stack Vnets and subnets that support both IPv4 and IPv6.
Azure VNet is not limited to one IP address space assignment. We can add more IP address spaces as needed, which is great for scalability! For example, we may want to add an additional IPv4 address space to support an unexpected workload expansion.
Limitation
Regardless of how many addresses are contained in the IP address spaces assigned to a Vnet, the total number of private IP addresses assigned to workloads cannot exceed 65,536.
The IP address spaces assigned to a Vnet do not have to be contiguous. Figure 1.6 shows an example of this with a Vnet that is configured to have two IPv4 address spaces that are not contiguous – 10.1.0.0/16
and 192.168.1.0/24
and an additional IPv6 address space for a dual-stack implementation – fd00:db8:deca::/48
.
Figure 1.6 – A Vnet with multiple address spaces
So, which IP address spaces should we use for our Vnets in Azure? Even though it is not required, it is highly recommended to use address ranges within the private, non-internet routable address spaces! For IPv4, this will be one of the IP ranges defined in RFC 1918 and for IPv6, this will be the Internet Engineering Task Force (IETF) defined Unique Local Addresses, which use the fc00::/7
address range.
RFC 1918 private IPv4 address ranges
Private IP address ranges defined in RFC 1918 are IP ranges that have been set aside by the IETF for private network use. They include the following:
•10.0.0.0/8
(10.0.0.0
– 10.255.255.255
)
•172.16.0.0/12
(172.16.0.0
– 172.31.255.255
)
•192.168.0.0/16
(192.168.0.0
– 192.168.255.255
)
Using any of the RFC 1918 private IP address ranges will require some form of address translation for internet routing and connectivity (we will cover this scenario later in this book).
Shared IPv4 address spaces reserved in RFC 6598 can also be used as they are treated as private IP address spaces in Azure. This range includes the following:
100.64/10
(100.64.0.0
– 100.127.255.255
)Other IP address spaces may work but they are not recommended as they could have undesirable routing side effects with instability! The following address ranges are not allowed to be used as Vnet IP address spaces:
224.0.0.0/4
(Multicast)255.255.255.255/32
(Broadcast)127.0.0.0/8
(Loopback)169.254.0.0/16
(Link-local)168.63.129.16/32
(Internal DNS)Whatever IP address ranges you decide to use for your Vnets, it is highly recommended to plan for non-overlapping IP address spaces across Azure regions and on-premises locations in advance. You can achieve this by defining an organization-wide IP address scheme that ensures that each network has its own unique private IP address space if it is an Azure network or an on-premises network.
Best practice
Define an organization-wide IP address scheme that ensures that each organization network has its own unique private IP address space.
One of the reasons why this is important is that it can impact your ability to connect networks together later or leave you in a situation where you need to implement sub-optimal network address translations that add to the complexity.
For example, you cannot connect two Vnets together via Vnet peering if they have the same address space! Figure 1.7 shows the error message that you will get if you attempt this:
Figure 1.7 – Vnets with overlapping address spaces cannot be peered
If you don’t know what Vnet peering is, don’t worry, we will cover it later in this book when we look at hybrid connectivity. You could use a VPN gateway to connect two networks with the same IP address spaces but this requires implementing address translation, which can make troubleshooting traffic flow very complex!
To provide isolation within a Vnet, we can divide it into one or more subnets. Subnets are primarily used for workload segmentation (logical perimeters within a Vnet). Figure 1.8 shows an example of this. In the diagram, we have a Vnet with two subnets. Web services are deployed into their own subnet (Web tier Subnet) and data services are deployed into their own subnet (Data tier Subnet).
With this approach, we can use an Azure route table to control how traffic is routed between the subnets. We can also use a network security group (NSG) or a network virtual appliance (NVA) to define allowed inbound/outbound traffic flow from/to the subnets (segments). The result of this is that if a part of our application stack is compromised, we are better placed to contain the impact of the security breach and mitigate the risk of lateral movement through the rest of our network. This is an important Zero Trust principle implementation. We will cover route tables, NSGs, and NVAs later in this book.
Figure 1.8 – Segmentation using subnets
How many subnets can Azure VNet have? It can have up to 3,000 subnets! Each subnet must have a unique IP address range that is within the defined IP address spaces of the Vnet (overlap is not allowed). For example, a Vnet with an IPv4 address space of 10.1.0.0/16
cannot have a subnet with an IP address range of 10.1.1.0/24
and another subnet with an address range of 10.1.1.0/25
as these ranges overlap with each other. Attempting to do so will result in the error message shown in Figure 1.9:
Figure 1.9 – Subnets with overlapping addresses not allowed
After defining the IP address range for a subnet, Azure reserves five IP addresses within each subnet that can’t be used! The first four IP addresses and the last IP address in an Azure subnet cannot be allocated to resources for the following reasons:
x.x.x.<first address>
: This is reserved for protocol conformance as the network addressx.x.x. <second address>
: This is reserved by Azure for the default gateway of the subnetx.x.x. <third address>
and x.x.x. <fourth address>
: This is reserved by Azure to map the Azure DNS IPs to the Vnet spacex.x.x. <last address>
: This is reserved for protocol conformance as the broadcast address (even though Azure Vnets don’t use broadcasts as we mentioned earlier)For example, if the IP address range of your subnet is 10.1.0.0/24
, the following addresses will be reserved:
This leaves a total of 250 addresses that can be allocated to subnet resources: 10.1.0.4
– 10.1.0.254
. Because of the required address reservation, the smallest supported IPv4 address prefix is /29, which gives five reserved addresses and three usable addresses. Specifying anything less leaves zero usable IPv4 addresses, which results in the error message shown in Figure 1.10:
Figure 1.10 – The smallest supported IPv4 address prefix for a subnet is /29
Note
The smallest supported size for an Azure IPv4 subnet is /29. The largest is /2.
If you are implementing a dual-stack design, the standard size of the assigned IPv6 address space should be /64. This is in line with the standard defined by the IETF. A /64 space is the smallest subnet that can be used locally if auto-configuration is desired. Any attempt to add an IPv6 address space that is not a /64 will result in the error message shown in Figure 1.11:
Figure 1.11 – Only a /64 address space assignment allowed for a subnet
When planning your subnets, make sure that you design for scalability. Workloads in your subnets should not cover the entire address space, giving you no room to add more workloads if needed. Plan and reserve some address space for the future. Also, take into consideration that some network resources such as the VMSS may need to dynamically add more workloads based on incoming requests. Modifying the IP address range of an Azure subnet that has workloads deployed is no straightforward task. It involves you removing all existing resources! Attempting this will result in the error message shown in Figure 1.12:
Figure 1.12 – The error message when trying to resize a subnet with resources
For most organizations, the main services that they will deploy into Azure VNet subnets are infrastructure-as-a-service (IaaS) services such as VMs and VMSSs but there are currently about 23 more services that can be deployed into a Vnet subnet, including platform services such as Azure SQL Managed Instance, App Service, Cache for Redis, and Azure Kubernetes Service. Deploying a supported platform service into a Vnet subnet is referred to as Vnet integration or Vnet injection.
A full list of services that are supported for VNet integration can be found at https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-for-azure-services#services-that-can-be-deployed-into-a-virtual-network.
There are about 25 services that can be deployed into a Vnet subnet, as shown in Figure 1.13:
Figure 1.13 – Various types of services supported for Vnet integration
Most PaaS services that support Vnet integration impose restrictions on the subnets that they can be deployed into, and this should be considered when planning your subnets. Here are some of the restrictions to consider:
Figure 1.14 – Two SQL-managed instances in the same dedicated subnet. Spring cloud requires dedicated subnets per instance
The key takeaway here is this – before deploying platform services into subnets, ensure that you follow the guidance in the service documentation regarding the aforementioned considerations to avoid inconsistencies in service functionalities. Always refer to the documentation for up-to-date information: https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-for-azure-services#services-that-can-be-deployed-into-a-virtual-network.
Now that you have some understanding of how to plan key aspects of Azure VNet, let us go ahead and get some implementation going!
In this exercise, we will create a single-stack IPv4 network for a fictional organization called CharisTech, which is in the process of migrating some on-premises applications to Azure. We will implement two VNets and subnets to support workloads that will be migrated. Here are the tasks that we will complete in this exercise:
Figure 1.15 shows the outcome that we’ll get to at the end of the tasks:
Figure 1.15 – CharisTech Azure VNets and subnets
A resource group is a logical container for managing related Azure resources. In this task, we will create a resource group called CharisTechRG that will hold the networking resources that we will create in other tasks:
Figure 1.16 – Create a resource
Figure 1.17 – Create a resource group
CharisTechRG
(2)Then, select Review + create (4):
Figure 1.18 – Creating a resource group
Figure 1.19 – Opening the newly created resource group
Leave this window open for the next task. Now that we have a resource group that we can use as a management container, let us proceed to create the VNets and subnets.
The first network that we will create is the CoreServicesVNet VNet (Figure 1.15). The network will be deployed in the East US region. It will be segmented into three subnets that will host the following workloads:
Let’s get started:
Virtual Network
. Select Virtual Network in the search results:Figure 1.20 – Creating a resource
CharisTechRG
CoreServicesVNet
Then, click Next: IP Addresses >:
Figure 1.21 – Creating the VNet
10.10.0.0/16
. Then, select + Add subnet:Figure 1.22 – Setting the IP address
SharedServicesSubnet
10.10.1.0/24
Then, click Add:
Figure 1.23 – Adding a subnet
Subnet |
Configuration option |
Configuration value |
DatabaseSubnet |
Subnet name |
DatabaseSubnet |
Subnet address range |
10.10.2.0/24 |
|
PublicWebServiceSubnet |
Subnet name |
PublicWebServiceSubnet |
Subnet address range |
10.10.3.0/24 |
Table 1.1 – Subnet configuration details
7. The configuration should look like Figure 1.24. Click on Review + create:
Figure 1.24 – Subnets added to the VNet configuration
8. Select Create. It should only take a few seconds to create the VNet and subnets.
Awesome! After the deployment completes, let us review what has been created.
In this task, we will review the resources created in the last task:
Figure 1.25 –Microsoft VNet overview
Figure 1.26 – Reviewing the subnets
You can leave this window open for the next task. Now that we have a resource group that we can use as a management container, let us proceed to create the VNets and subnets.
In this exercise, we will create a dual-stack network in Azure that supports both IPv4 and IPv6 for the fictional organization called CharisTech. The activities in this task will be completed using the Azure CLI to give you familiarity with the different Azure management tools. Here are the tasks that we will complete in this exercise:
Figure 1.27 shows the outcome that we’ll get to at the end of the tasks:
Figure 1.27 – CharisTech Azure VNets and subnets
Figure 1.28 – Click the icon to open Cloud Shell
Figure 1.29 – Select the Bash shell environment
group=CharisTechRG location=westus VNet=EngineeringVNet
az network VNet create
command. The following command creates a VNet named EngineeringVNet
with one subnet named EngSubnet1
. Both the VNet and the subnet are dual-stack:az network VNet create --name $VNet --resource-group $group --location $location --address-prefixes "10.20.0.0/16" "fd00:db8:deca::/48" --subnet-name EngSubnet1 --subnet-prefix "10.20.1.0/24" "fd00:db8:deca:1::/64"
az network VNet subnet create
command. The following command adds a dual-stack subnet named EngSubnet2
to the EngineeringVNet
network that we created earlier:az network VNet subnet create -n EngSubnet2 --address-prefixes "10.20.2.0/24" "fd00:db8:deca:2::/64" --resource-group $group --VNet-name $VNet
Now that the dual-stack VNets and subnets are created, let us verify them.
az network VNet list --resource-group CharisTechRG --output table
The output should be like the output shown in Figure 1.30:
Figure 1.30 – The VNet list output
As you can see, using command-line management tools such as the Azure CLI greatly streamlines resource management in Azure!
When resources are deployed into an Azure VNet subnet, a private IP address is automatically assigned from the subnet’s address range. If the subnet is a single-stack subnet (IPv4 only), Azure assigns an IPv4 address to the workload. If the subnet is a dual-stack subnet (both IPv4 and IPv6), Azure assigns both an IPv4 and an IPv6 address if the service supports IPv6 assignments. As of the time of writing, only VMs and VMSS NICs support both IPv4 and IPv6, other VNet services/resources support only IPv4 private IP assignments.
There are two methods for private IP assignments in an Azure VNet subnet (Figure 1.31):
10.10.1.0/24
address range, if the 10.10.1.4
address is already assigned to another resource, the next available address – 10.10.1.5
– is automatically assigned to the next resource. This method is the default allocation method for all VNet resources, including VNet-integrated platform services. For VM and VMSS NICs, dynamic IP addresses are released if a network interface is deleted or re-assigned to a different subnet within the same VNet.Figure 1.31 – VNet resource private IP assignment options
Figure 1.32 – Static IP assignment for a VNet deployed Cache for Redis resource
As a general rule, you should avoid static private IP assignments as much as possible. This is because cloud-hosted workloads are usually dynamic with capabilities such as auto-scaling that allow resources to be added/removed in response to the volume of requests being received. Using the default dynamic assignment method means that we have one less thing to worry about.
It is also important to note that VM network interfaces can have more than one private IP assignment (Figure 1.33). Actually, they can have up to 256 private IP assignments!
Figure 1.33 – Multiple private IP assignments for a VM NIC
Enough discussion for now; let us review this in practice. But first, we need to determine the locations and VM sizes that we will be using.
To complete some of the hands-on exercises in this book (such as the exercise after this one), you will need to deploy VMs for testing. In Azure, not all VM sizes are available in all subscription regions! There are also CPU quota limits for VM families and subscription regions (Figure 1.34).
Figure 1.34 – Regional and VM family CPU limits per subscription
In this exercise, you will evaluate your subscription to determine the VM sizes and locations to use for the exercises in the upcoming chapters of this book. Here are the tasks that you will complete in this exercise:
For the hands-on exercise, I will be defaulting to the East US and West US Azure regions as these are the regions that I have used throughout the rest of the book. While I recommend that you also use these regions, you do not need to stick with this recommendation. There is nothing particular about them. If you decide to use other regions instead, simply replace the values as you run the specified commands. You can obtain a list of Azure locations with the az account list-locations -o table Azure CLI command.
Let’s get into this!
The steps are as follows:
Figure 1.35 – Click the icon to open Cloud Shell
Figure 1.36 – Select the Bash shell environment
az vm list-usage --location eastus --output table az vm list-usage --location westus --output table
Figure 1.37 – The total regional vCPU usage
Figure 1.38 – Standard BS VM Family regional vCPU usage
Standard_B
VM family in the East US and West US Azure regions. I will be defaulting to a VM size in this VM family. If you plan on using different regions, remember to replace the value for the location parameter with the regions that you are planning to use:az vm list-skus --location eastus --size Standard_B --all --query "[?restrictions[0].reasonCode != \`NotAvailableForSubscription\`]" --output table az vm list-skus --location westus --size Standard_B --all --query "[?restrictions[0].reasonCode != \`NotAvailableForSubscription\`]" --output table
Figure 1.39 – The Standard_B2s VM size availability check
Now that you have verified the regions and VM size that you will be using, make a note of these as you will be needing them in the upcoming exercises in this chapter and in the rest of the chapters of this book.
In this exercise, you will explore private IP assignment options for VNet resources. Here are the tasks that you will complete in this exercise:
Let’s get into this!
The steps are as follows:
Standard_B2s
value if you are using a different size than you verified in the previous exercise:group=CharisTechRG location=eastus VNet=CoreServicesVNet subnet=PublicWebServiceSubnet size=Standard_B2s
WebVM0
into PublicWebServiceSubnet
of CoreServicesVNet
with the az vm create
command. This will default to the dynamic private IP assignment method:az vm create -g $group -n WebVM0 --image UbuntuLTS --admin-username azureuser --generate-ssh-keys --VNet-name $VNet --subnet $subnet --size $size --public-ip-address ""
The following figure shows the output of this command. Ignore the warning about the public IP as the VM is created without a public IP assigned.
Figure 1.40 – VM creation with the default dynamic private IP assignment
WebVM1
into PublicWebServiceSubnet
of CoreServicesVNet
with the az vm create
command. This time around, we will specify a static private IP assignment of 10.10.3.10
:az vm create -g $group -n WebVM1 --image UbuntuLTS --admin-username azureuser --generate-ssh-keys --VNet-name $VNet --subnet $subnet --size $size --public-ip-address "" --private-ip-address "10.10.3.10"
The following figure shows the output of this command. Ignore the warning about the public IP as the VM is created without a public IP assigned.
Figure 1.41 – VM creation with the default dynamic private IP assignment
az network nic
list
command:az network nic list -g $group --query "[*].{NIC:name, PrivateIP: ipConfigurations[0].privateIpAddress, Assignment: ipConfigurations[0].privateIpAllocationMethod, IPVersion: ipConfigurations[0].privateIpAddressVersion}" -o table
The --query
parameter is used to sort through the JSON array response to select the properties that we are interested in. The following screenshot shows what the output looks like:
Figure 1.42 – The VM NIC dynamic private IP assignment
Leave Cloud Shell open for the last exercise in this chapter.
In this exercise, we will remove the resources that we created in the chapter exercises to avoid running up a large cost in Azure!
In Cloud Shell, run the following command to delete the CharisTechRG
resource group. This will remove all the resources that we created for the exercises in this chapter:
az group delete --name CharisTechRG --yes
In this chapter, we covered an overview of what Azure VNet is. We discussed core VNet planning concepts such as designing a consistent naming scheme, which is critical to resource identification, especially in logging scenarios that we will cover later in this book. We discussed key considerations around selecting the right regions to deploy your networks into, specifying an IP address space that scales, and implementing private IP assignments.
We also carried out hands-on exercises on creating single-stack and dual-stack VNets, determining VM location and sizes for future exercises, and exploring private IP assignments to further solidify the concepts that you learned in this chapter.
The skills that you gained in this chapter are foundational to your being able to design reliable network architectures in Azure to host business-critical applications.
Azure network engineering is a deep and complex topic and we’re only just starting to scratch the surface. In the next chapter, we will cover one of the most important aspects of designing scalable networks in Azure – DNS.
For more information about the topics covered in this chapter, you can refer to the following:
Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.
If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.
Please Note: Packt eBooks are non-returnable and non-refundable.
Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:
If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:
Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.
You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.
Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.
When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.
For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.