Thursday, April 28, 2011

Integrating DHCP, DNS, NTP, NAT, IOS Firewall, Port Forwarding, IPsec VPN and WiFi Services Into a Single Cisco Router For Small Businesses

In the past year, a couple of my small business customers gave me the task to upgrade their Internet access router to a more robust one.  Their Linksys/D-Link wasn’t up to the task anymore and kept having to be rebooted or had other problems.  So, I decided it was time to ditch the consumer-grade routers for business-oriented hardware.  Based on Cisco marketing materials, I thought the newer Integrated Services Routers (ISR) might be relatively easy to configure to accomplish this upgrade.  I would later discover it wasn’t so obvious! 

At the beginning, my customers gave me the following requirements:

- Employees must be able to securely access the internal LAN from anywhere on the Internet

- Contractors must also have secure access to the internal LAN but be  restricted to a single machine since there is no need for them to use any other internal resources

- DNS name resolution by internal LAN hosts for the company’s own zone must resolve to internal IP addresses

- DNS name resolution for all other zones as well as the company’s own external addresses should use the ISP DNS servers

These small businesses did not have a DNS server or any LDAP directory of any kind.  One had mostly Mac computers and a development server hosting test web sites for its clients.  And the other was so small (a few computers, and a NAS appliance) that I decided a Cisco 871W router would probably be adequate.

The Cisco 871 turned out to be a good choice for these environments.  However, I had problems integrating the different services needed into one box.  There are so many choices of different technologies in IOS for accomplishing the same task, that it sometimes becomes difficult to choose components that work well together in the same box.  For example, I needed to ensure CBAC (the IOS Firewall), PAT (NAT overload), inbound static NAT (port forwarding), remote access IPSec VPN, NTP, DNS, the DHCP service and a WiFi guest network in addition to the regular private secure network could all co-exist together. 

I will share a configuration that took me months to write and test in hope it will save some of you time.

First, I always start with the IP addressing scheme.  It is easier to write configurations if the IP addresses are already chosen.  I will explain how I came up with each subnet shortly:

Company/Site Summary:  192.168.64.0/22

Internal LAN (VLAN101): 192.168.64.0/25

Guest LAN (VLAN102): 192.168.64.128/25

Loopback0: 192.168.67.249/32

Loopback1: 192.168.67.252/30

Employee remote access VPN pool: 192.168.66.0/25

Contractor remote access VPN pool: 192.168.66.128/25

Available/unused: 192.168.65.0/24, 192.168.67.0/25, 192.168.67.128/26, 192.168.67.192/27, 192.168.67.224/28, 192.168.67.240/29, 192.168.67.250/32

I typically choose /25 subnets for the LAN segments because that gives more than enough (block of 126) usable addresses for all situations in a small business.  A /24 would be fine as well.  Keep in mind that a Cisco 871 is sized for a site with less than 20 users and less than 20 outside VPN remote access users.  So, a /25 is already overkill here, however, it’s good practice to size the IP addressing so it never needs to be changed in case of expansion because re-IP projects are never fun, although, the router itself is easy enough to upgrade with the existing addressing.  Don’t assign more than a /24 (block of 254) as that’s generally not good practice and broadcasts on the subnet may become an issue when all addresses become utilized.

The /22 site summary is a bit arbitrary in this case because it’s a single site company but it helps in my mind to establish boundaries from the beginning, even if they have to eventually change.  This way, if the company is bought out or acquires another, it’s then pretty clear what needs to happen from a network standpoint as long as it’s clearly documented.

The loopback0 address is the main IP for the router, and I use it to manage it, and point clients to it for DNS queries, etc.

Finally, the loopback1 address is required for static NAT bypass, as I’ll describe later in this article.

To get started, choose an IOS version.  Make sure you purchase the router with an appropriate IOS feature set as well as a service contract, which allows access to the cisco.com download section.  Keep in mind, the IOS that comes with the router may not be the one you need.  Although make sure that if you purchase the router with a specific feature set, you stick to it, otherwise you might violate the licensing agreement.

For my two deployments, I installed the ADVANCED SECURITY feature set and initially chose 12.4(22)T1 because it had the new object groups I found useful when I was configuring PIX firewalls in the past.  It is also a recent enough version which  includes all the above services I was mentioning earlier.  I discovered however that the newer DNS View service had a bug (ID # CSCsx53968) which logged the following error each time the router received a DNS query:

%FIB-4-FIBCBLK: Missing cef table for tableid 65535 during CEF samecable event

So, I waited for the fix in 12.4(22)T2.  This is the IOS version running today on my routers, which is not perfect, but doesn’t contain any show stoppers.  I’ll discuss this in more details shortly.

Now that we have the correct IOS running, we can begin the configuration.  We’ll start with just the basics to enable Internet connectivity through the router using NAT, DHCP and CBAC.  I assume we are starting with a blank configuration, meaning an “erase startup-config” and “reload” was done.

First, the access list that will work in conjunction with CBAC.  It will allow only specifically permitted traffic to enter the router through Fa4:

ip access-list extended ACL_INTERNET_TO_FA4
 remark SSH FOR MANAGEMENT FROM THE INTERNET
 permit tcp any any eq 22 log ALLOW_SSH
 remark REMOTE ACCESS VPN
 permit esp any any
 permit udp any any eq isakmp
 permit udp any any eq non500-isakmp
 remark PORT FORWARDING
 permit tcp any any eq www

Then, a basic CBAC inspect list.  Normally, you would probably add layer 7 applications to this list, however the layer 4 transports are good enough, meaning they cover all connectivity that will be needed for the end-users for this demonstration.  Also, the “router-traffic” keyword is needed because we want traffic originated in the router to be inspected by CBAC, and consequently its return traffic allowed back in.  For example, if I am logged into the router, I want to be able to ping a host on the Internet and have my echo-replies allowed back in via Fa4.  If I didn’t have “icmp router-traffic”, return packets would be dropped by the implicit “deny ip any any” in ACL_INTERNET_TO_FA4.  I do not plan on having any TCP traffic initiated by the router out to the Internet, so the “router-traffic” keyword for “tcp” is not necessary.

ip inspect name CBAC_INS_OUT icmp router-traffic
ip inspect name CBAC_INS_OUT tcp
ip inspect name CBAC_INS_OUT udp router-traffic

Then we prepare the outbound NAT access list for outside interface Fa4.  In other words, this access list determines which traffic doesn’t get translated (VPN traffic) and which does (all other traffic).

ip access-list extended ACL_NAT
 remark TRAFFIC NOT TRANSLATED
 deny   ip 192.168.64.0 0.0.3.255 192.168.66.0 0.0.0.255
 remark NAT TRAFFIC
 permit ip 192.168.64.0 0.0.3.255 any

A route map will also be needed for applying the NAT list we created to the outside interface later on:

route-map RM_NAT permit 10
 match ip address ACL_NAT

We now have almost everything we need to enable connectivity.  The last few pieces are DHCP and to apply the CBAC and NAT config to our outside interface.  In the following DHCP server config, we exclude the first 63 addresses including the default gateway from the scope.  We also assign a domain name to our DHCP client interfaces, a default gateway, and some DNS servers.  Notice that for VLAN 101, we assign the router’s loopback0 address as the DNS server.  For VLAN 102, we don’t want guest users to use the router for their DNS queries, so we assign public Internet DNS servers (4.2.2.1 and 208.67.222.222) instead.

ip dhcp excluded-address 192.168.64.1 192.168.64.63
ip dhcp excluded-address 192.168.64.129 192.168.64.191
ip dhcp pool POOL_DHCP_VLAN101
   network 192.168.64.0 255.255.255.128
   domain-name example.com
   default-router 192.168.64.1 
   dns-server 192.168.67.249
ip dhcp pool POOL_DHCP_VLAN102
   network 192.168.64.128 255.255.255.128
   default-router 192.168.64.129 
   dns-server 4.2.2.1 208.67.222.222 
   domain-name example.com
   lease 0 1

Lets now configure the interfaces, our final piece in establishing basic ‘wired’ connectivity.  Wireless will be added later.  The “bridge irb”, “bridge 101 route ip” and “bridge 102 route ip” are used to bridge VLAN 101 across the physical FastEthernet interfaces as well as the radio interfaces.  Same thing for VLAN 102.  This way, you can have a single VLAN used across different media.  That’s how most consumer-grade routers are configured by default.  The BVI interfaces are used to assign an IP address for the router for the bridge group.  These BVI interfaces become the “entry point” into the router from the two different bridged media.  So, a simple way to think about traffic flow is traffic on VLAN 101 and the dot11radio0.101 (interface to be configured later) will always enter the router via BVI101, which will now be the place where we can configure access groups and other interface commands if needed.

bridge irb

int lo0
 ip address 192.168.67.249 255.255.255.255

int fa4
 description ISP
 ip address 69.x.y.z 255.255.255.252
 ip access-group ACL_INTERNET_TO_FA4 in
 ip inspect CBAC_INS_OUT out
 ip nat outside

int vlan101
 description EMPLOYEES_192.168.64.0/25
 no ip address
 ip nat inside
 bridge-group 101
 bridge-group 101 spanning-disabled
 no shut

int vlan102
 description GUESTS_192.168.64.128/25
 no ip address
 ip nat inside
 bridge-group 102
 bridge-group 102 spanning-disabled
 no shut

interface BVI101
 ip address 192.168.64.1 255.255.255.128
 ip nat inside

interface BVI102
 ip address 192.168.64.129 255.255.255.128
 ip nat inside

int range fa0-3
 switchport access vlan 101

bridge 101 route ip
bridge 102 route ip

ip nat inside source route-map RM_NAT interface Fa4 overload

With all that, you should now be able to connect a computer into one of the switch ports and ping a host on the Internet.  You should also be able to ping that same host from the router command line interface (CLI).

Now we need to add internal DNS services for VLAN 101.  We will also be able to leverage this DNS server for our VPN clients once configured.  First add internal host records:

ip host contractors.example.com 192.168.64.8
ip host client.dev.example.com 192.168.64.9
ip host router-vlan101.example.com 192.168.64.1
ip host router.example.com 192.168.67.249

Then create the default DNS server attributes and forwarders.  This tells the router to query these servers if it can’t resolve a name.  In other words, for all other names except the ones in the above “ip host” commands:

ip dns view default
 domain name example.com
 domain name-server 4.2.2.1
 domain name-server 208.67.222.222
exit

Create a DNS view list that will call the default view above:

ip dns view-list DNS_VIEW_LIST
 view default 20
exit

Enable the DNS service:

ip dns server

Apply the DNS view list to interface BVI101, which is the interface that will receive all traffic from VLAN 101 (the internal wired LAN) and dot11radio0.101 (the internal wireless LAN).  It receives all traffic from internal hosts because it is the default gateway, as assigned to the hosts by our DHCP configuration above.

int BVI101
 ip dns view-group DNS_VIEW_LIST
exit

At this time, internal clients should be able to resolve the host records we added above, as well as Internet hosts.  Note- there are many more Cisco DNS View commands available including some to turn a router into an authoritative DNS server, among other things.  I have not found a need to use them in any of my small business customer networks so far.  If anyone has experience setting up more complex “real world” DNS configurations, feel free to comment or email me.

Port forwarding – one of my two customers needed their business partners to be able to HTTP to one of the internal development server on premises.  Normally, I would have suggested to locate the server in a datacenter colocation facility, so it would be attached to highly-available switches, and benefit from dual-homed ISP, as well as proper DMZ security.  However, in this case, for several reasons, it made more sense to keep it on premises.  So, I had to port-forward this TCP traffic to it.  To accomplish this, the ACL applied inbound on Fa4 needs to allow TCP port 80.  We already prepared ACL “ACL_INTERNET_TO_FA4” above with “permit tcp any any eq www” for this.  We also need to add our static NAT command which will forward all TCP Port 80 traffic received on interface Fa4 to 192.168.64.9:

ip nat inside source static tcp 192.168.64.9 80 int Fa4 80

This setup will work just fine except for remote access VPN clients.  If we were to leave the configuration as is, the Cisco VPN Clients would be subject to the static NAT command for return traffic.  In other words, the router will try to put a global public IP address into the packet’s destination field before sending the packet out interface Fa4 instead of the internal VPN pool address, and the connections will fail.  Therefore, even if you have no remote access VPN on the router, I still suggest to complete the configuration as follows to prevent headaches later.  Create a Loopback1 interface with a /30 mask, and direct all traffic passing from the internal LAN 192.168.64.0/25 to the VPN pools 192.168.66.0/25 & 192.168.66.128/25 (summarized as 192.168.66.0/24) to make an extra hop to bypass the static NAT by using a route-map and IP local policy:

int lo1
 desc STATIC_NAT_BYPASS_192.168.67.252/30
 ip address 192.168.67.253 255.255.255.252

ip access-list extended ACL_NAT_STATIC
 permit ip 192.168.64.0 0.0.0.127 192.168.66.0 0.0.0.255

route-map RM_NAT_STATIC permit 10
 match ip address ACL_NAT_STATIC
 set ip next-hop 192.168.67.254

int bvi101
 ip policy route-map RM_NAT_STATIC
exit

Now we will add the remote access VPN configuration.  There are several methods to do this, however, I’ve tried to use the most recent IOS commands including IPsec profiles, which were introduced with DMVPN but can also be useful to simplify our configuration.

This first step is to make sure the VPN traffic does not get NAT translated.  We need to be able to connect between 192.168.66.0/24 and the internal addresses via this NAT router.  We’ve already accomplished this by preparing our access list “ACL_NAT” above with the command “deny ip 192.168.64.0 0.0.3.255 192.168.66.0 0.0.0.255”.  The site/company summary 192.168.64.0 0.0.3.255 is used here because we want nothing in that range to ever translate when going to 192.168.66.0/24. 

Secondly, we’ll create the VPN IP address pools:

ip local pool POOL_RAS_VPN_EMPLOYEES 192.168.66.1 192.168.66.126

ip local pool POOL_RAS_VPN_CONTRACTORS 192.168.66.129 192.168.66.254

Third, we need to create access lists to tell the router what traffic to encrypt.  We’ll need one for the employees VPN group and one for the contractor VPN group.  The employees will have access to the entire LAN, while the contractors will only have access to the machine at 192.168.66.8.

ip access-list extended ACL_CRYPTO_RAS_VPN_EMPLOYEES
 permit ip 192.168.64.0 0.0.3.255 192.168.66.0 0.0.0.127

ip access-list extended ACL_CRYPTO_RAS_VPN_CONTRACTORS
 permit ip host 192.168.64.8 192.168.66.128 0.0.0.127

Normally, for a more robust setup, at a larger company, we’d have a RADIUS or TACACS+ server to provision user accounts for remote access VPN.  However, here, we use the local AAA service on the router.

aaa new-model
aaa authentication login AAA_AUTHEN_LOGIN_LOCAL local
aaa authorization network AAA_AUTHOR_NETWORK_LOCAL local

username testuser secret testpassword

Create the IKE policy using pre-shared keys, DH group 2, and 3DES encryption:

crypto isakmp policy 30
 encr 3des
 authentication pre-share
 group 2

Create the two IKE VPN groups and assign a domain name, as well as our DNS server IP address so the clients can resolve our internal names.  Each group also has a different IP address pool so we can configure access lists to restrict traffic further if we need.

crypto isa client configu group EXAMPLE_GROUP_EMPLOYEES
 key EXAMPLE_KEY_EMPLOYEES
 dns 192.168.67.249
 domain example.com
 pool POOL_RAS_VPN_EMPLOYEES
 acl ACL_CRYPTO_RAS_VPN_EMPLOYEES

crypto isa client configu group EXAMPLE_GROUP_CONTRACTORS
 key EXAMPLE_KEY_CONTRACTORS
 dns 192.168.67.249
 domain example.com
 pool POOL_RAS_VPN_CONTRACTORS
 acl ACL_CRYPTO_RAS_VPN_CONTRACTORS

Create profiles with appropriate local authentication and assign the VPN groups to their individual profiles so they can be used in crypto maps later on.

crypto isakmp profile PROFILE_IKE_RAS_VPN_EMPLOYEES
   description Cisco VPN clients profile for employees
   match identity group EXAMPLE_GROUP_EMPLOYEES
   client authentication list AAA_AUTHEN_LOGIN_LOCAL
   isakmp authorization list AAA_AUTHOR_NETWORK_LOCAL
   client configuration address respond

crypto isakmp profile PROFILE_IKE_RAS_VPN_CONTRACTORS
   description Cisco VPN clients profile for contractors
   match identity group EXAMPLE_GROUP_CONTRACTORS
   client authentication list AAA_AUTHEN_LOGIN_LOCAL
   isakmp authorization list AAA_AUTHOR_NETWORK_LOCAL
   client configuration address respond

Create a transform set with 3DES/ESP/SHA encryption for our VPN traffic:

crypto ipsec transform-set ESP-3DES-SHA esp-3des esp-sha-hmac

Create a dynamic crypto map which can be assigned to clients that negotiate dynamic IP addresses, which happens to be all clients, as opposed to a site-to-site tunnel between two static, public IP addresses.  Associate the profiles to this transform set:

crypto dynamic-map CRYPTO_DYN_MAP 20
 set transform-set ESP-3DES-SHA 
 set isakmp-profile PROFILE_IKE_RAS_VPN_CLIENTS

crypto dynamic-map CRYPTO_DYN_MAP 30
 set transform-set ESP-3DES-SHA 
 set isakmp-profile PROFILE_IKE_RAS_VPN_CONTRACTORS

Assign the dynamic crypto map to a crypto map that can then be applied to our external interface Fa4:

crypto map CRYPTO_MAP 110 ipsec-isakmp dyn CRYPTO_DYN_MAP

int fa4
 crypto map CRYPTO_MAP

At this point, the router is ready to accept Cisco VPN Client connections configured with the VPN groups and keys.  Clients will also be prompted with extended authentication verified against local username commands.  Once connected, VPN clients should also be able to use the router to resolve DNS names, as opposed to normally using the DNS servers received by their ISP. 

One problem however:  Testing this function indeed shows that clients obtained the correct DNS server of 192.168.67.249, but that address is neither responding to ping nor DNS queries (UDP port 53).  Troubleshooting reveals this is an IOS bug relating to CBAC’s “router-traffic” command, which we applied to ICMP and UDP in our inspect list above.  Removing the “router-traffic” keyword fixes the issue but also prevents the router from being able to initiate UDP and ICMP connections to hosts on the Internet.  In our case, the router needs NTP to sync its clock with an NTP server, so we cannot remove the “udp router-traffic” from our config.  I reported the problem to Cisco several weeks ago, and they are working on a fix.  The bug ID number is CSCtd40862.  While troubleshooting, I discovered the workaround is to add an additional entry in ACL_INTERNET_TO_FA4 to allow traffic from the VPN pools to reach the Loopback0 interface address.  This is clearly a workaround until a fixed IOS image is released:

ip access-list extended ACL_INTERNET_TO_FA4
permit ip 192.168.66.0 0.0.0.255 host 192.168.67.249 log TEMP_TIL_IOS_BUG_FIX

permit ip 192.168.66.0 0.0.0.255 host 192.168.64.1 log TEMP_TIL_IOS_BUG_FIX
end

UPDATE- 4/28/2011 – Cisco has fixed this bug in their IOS 15.1(3)T and 12.4(24)T5 images.  I tested both and the above “TEMP_TIL_IOS_BUG_FIX” entry is no longer needed. 

The VPN traffic can now successfully reach our router’s Loopback0 for its DNS queries, as well as the BVI101 address if ever needed for troubleshooting via ICMP echo.

Finally, let’s configure our wireless infrastructure.  As stated above, we will enable both the private and guest subnets for wireless access. 

Both wireless LANs will be configured with WPA-PSK with AES encryption for the sake of preventing data confidentiality and other breaches.  The guest network will have a short, well known (provided to guests) WPA pre-shared key while the internal WLAN will have a longer (20 characters or more), difficult to crack one.  The guest network could just as well be open (no encryption) and left for users to protect themselves by using a technology of their choice such as VPN, SSL, etc.

dot11 vlan-name VLAN101_192.168.64.0/25 vlan 101
dot11 vlan-name VLAN102_192.168.64.128/25 vlan 102

dot11 ssid EXAMPLE
 vlan 101
 authentication open 
 authentication key-management wpa
 wpa-psk ascii EXAMPLE_WPA_PSK101

dot11 ssid EXAMPLE_GUEST
 vlan 102
 authentication open 
 authentication key-management wpa
 guest-mode
 wpa-psk ascii EXAMPLE_WPA_PSK102

interface Dot11Radio0
 no ip address
 no dot11 extension aironet
 encryption vlan 101 mode ciphers aes-ccm 
 encryption vlan 102 mode ciphers aes-ccm 
 ssid EXAMPLE
 ssid EXAMPLE_GUEST
 speed basic-1.0 basic-2.0 basic-5.5 6.0 9.0 basic-11.0 12.0 18.0 24.0 36.0 48.0 54.0
 station-role root
 no cdp enable

interface Dot11Radio0.101
 encapsulation dot1Q 101
 no cdp enable
 bridge-group 101
 bridge-group 101 subscriber-loop-control
 bridge-group 101 spanning-disabled
 bridge-group 101 block-unknown-source
 no bridge-group 101 source-learning
 no bridge-group 101 unicast-flooding

interface Dot11Radio0.102
 encapsulation dot1Q 102
 no cdp enable
 bridge-group 102
 bridge-group 102 subscriber-loop-control
 bridge-group 102 spanning-disabled
 bridge-group 102 block-unknown-source
 no bridge-group 102 source-learning
 no bridge-group 102 unicast-flooding

With the above, the guest BSSID (EXAMPLE_GUEST) will be broadcasted, while the other one (EXAMPLE) will not.  So, it will be clear to guests which BSSID they need to associate to.

We now need to prevent traffic from the guest VLAN to connect to anything in the company summary except its own subnet and the Internet:

ip access-list extended ACL_VLAN102_TO_BVI102
 permit ip any 192.168.64.128 0.0.0.127
 deny   ip any 192.168.64.0 0.0.3.255
 permit ip any any

int bvi102
ip access-group ACL_VLAN102_TO_BVI102 in
end

This was a long blog post to write!  Let me know if it was useful and if you have comments, corrections, etc.  Thanks for reading.