Thursday, November 14, 2013

JNCIA Lesson 4 1/2 -- More on Routing Policies and Firewall Filtering

One of the concepts that I have struggled with the most while trying to learn JunOS is the filtering language used on Juniper devices. That's a pretty significant problem too, because the filtering language is basically a core feature of JunOS, cropping up in Class of Service/Quality of Service, routing policies, and, of course, basic firewall/security on JunOS devices. It's pretty safe to say that if you don't understand this core concept, you will not be proficient in JunOS, and therefore, I decided I needed to spend a little while playing with the filtering syntax so I can understand it better. In it's most basic form, the filtering rules follow the pattern, "match-action" -- that is, you define a pattern to match, then upon a match, you perform some action on incoming packets -- and then you apply the filter to an interface or VLAN. There are three important concepts to keep in mind when trying to compose a filter rule:
  1. Within a single term, match rules are logical-AND'ed together. That is, if you put a rule to match a source IP address inside a term, then put a second rule to match a destination port, the filter will only match packets from that particular source IP address AND to that particular destination port (i.e., from 192.168.1.17, to port 23). If you want to logically OR rules, you have to create separate terms in the firewall rule-set;
  2. Packets are compared to each term from the top down, and the firewall stops comparing the packet to the firewall rules when it finds a match. In other words, if you put an "allow any" rule as the first term in your match rules, then put specific "deny ..." rules below, all packets will match against the "allow any" and no packet will ever be compared against the "deny ..." rules;
  3. There is an implicit "deny all" at the very end of the firewall rules, even though it is not shown in the configuration. Therefore, you must always make sure that you include rules to match all of the traffic that you want to allow. For example, suppose you are seeing brute-force password guessing attacks through SSH from the IP address 1.2.3.4, so you create a rule to drop traffic matching the source address of 1.2.3.4 and destination port 22. Unless you configure a rule to allow everything else, the implicit "deny all" rule will drop all traffic coming in on the interface or VLAN to which you applied the firewall rule.


Let's start with a simple example: suppose I have a switch on the 192.168.1.0/24 network, I have a host at 192.168.1.1, and on my switch, I want to block ICMP messages from that host with an "ICMP Administratively Prohibited" notification, while allowing any other protocol from 192.168.1.1 or all traffic from other source addresses.

root@branch-3200# set firewall family inet filter no-icmp term drop-icmp from source-address 192.168.1.1

[edit]
root@branch-3200# set firewall family inet filter no-icmp term drop-icmp from protocol icmp

[edit]
root@branch-3200# set firewall family inet filter no-icmp term drop-icmp then reject administratively-prohibited

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


If we attempt to ping 192.168.1.2 (the EX3200 switch) from 192.168.1.1 at this point, we will find the firewall isn't particularly effective:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=3.630 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=2.408 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=2.395 ms
^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 2.395/2.811/3.630/0.579 ms

root@main3200>


Since we haven't applied the firewall to an interface or VLAN yet, no incoming packets are being compared against the firewall rules, and therefore all inbound traffic is still allowed. Let's take care of that, now:

root@branch-3200# set interfaces vlan unit 0 family inet filter input no-icmp

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


To create our firewall, we started by adding a rule that drops traffic only if the source address is 192.168.1.1. However, we only want to drop ICMP traffic, so we then added a second rule (with the same term name, namely "drop-icmp") that drops ICMP traffic. Since the terms are cumulative, we've essentially created a rule that says, "if the source address matches 192.168.1.1 AND the protocol is ICMP..." Then, we created an action to reject matching packets with the "administratively prohibited" message. Let's see how it works:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 d4e0   0 0000  40  01 2275 192.168.1.1  192.168.1.2
<...snip...>
^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
root@main3200>


Good, good...

root@main3200> telnet 192.168.1.2
Trying 192.168.1.2...
telnet: connect to address 192.168.1.2: Operation timed out
telnet: Unable to connect to remote host

root@main3200>


Hrmmm...Well, we're half-way there. We are successfully blocking ICMP, but apparently, we are also blocking telnet. Remember, JunOS adds an implicit "deny all" at the end of the firewall rules. Since we create a rule to block ICMP from 192.168.1.1, but we didn't include a rule to allow any packets, we are actually blocking ALL packets on vlan.0. To fix this, we have to add a new term to allow anything that isn't ICMP and from 192.168.1.1:

root@branch-3200# set firewall family inet filter no-icmp term everything-else source 0.0.0.0/0

[edit]
root@branch-3200# set firewall family inet filter no-icmp term everything-else then accept

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


Let's see if that solves the problem:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f4c   0 0000  40  01 c809 192.168.1.1  192.168.1.2

36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f76   0 0000  40  01 c7df 192.168.1.1  192.168.1.2

36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f9c   0 0000  40  01 c7b9 192.168.1.1  192.168.1.2

^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

root@main3200> telnet 192.168.1.2
Trying 192.168.1.2...
Connected to 192.168.1.2.
Escape character is '^]'.

branch-3200 (ttyp0)

login:
telnet> quit
Connection closed.

root@main3200>


That's more better :) We are now successfully blocking ICMP from 192.168.1.1 while still allowing other protocols, such as TCP/23 (telnet) to the switch.

However, looking at the firewall rules, something doesn't seem to be right. We have two rules to block source-address 192.168.1.1 and protocol ICMP, but the allow rule only specifies a source-address. How does this rule work?

Keep in mind that JunOS firewall rules work from top down, and they stop looking for matches as soon as a packet matches a term. Consequently, any packet originating from 192.168.1.1 and using the ICMP protocol matches our "reject ..." rule. However, if the packet comes from another source address or is a protocol other than ICMP, JunOS continues comparing the packet with the firewall rules. Therefore, anything not matching the "drop-icmp" term is compared to the "everything-else" term. The "everything-else" term tries to match the packet against the source-address of 0.0.0.0/0 -- in other words, against all possible source IP addresses. Since this second term will match a packet coming from any IP address, it is essentially an "allow any" rule. Therefore, our rule effectively reads, "if the packet matches 192.168.1.1 and matches the ICMP protocol, then reject it with the 'administratively-prohibited' message. If it is anything else, allow it."

Wednesday, November 13, 2013

JNCIA Lesson 8 -- Link Aggregation

In the lesson on Spanning Tree, we addressed the issue of redundancy, but what if your users are consuming more bandwidth than a single Gig-E uplink port can provide? STP/RSTP/MSTP allows you to connect multiple links between switches, but only ONE path can be active at any time, so you are still limited to 1Gbps between switches (assuming a Gig-E switch, of course).

Fortunately, there is a standardized protocol, known as "Link Aggregation Control Protocol" (LACP) or sometimes simply "LAG" (Link AGgregation) for creating bundled Ethernet links between switches. That is, in much the same way that a T1 line is a bundle of individual 64kbps lines that have been concatenated together to provide 1.544Mbps of bandwidth, there is also a way to bundle several individual Ethernet channels together to create a single, virtual channel with a bandwidth equal to the sum of the physical Ethernet links in the bundle. For example, if we were to take two Gig-E ports on our EX3200 switches and aggregate them together using LACP, we would have a 2Gbps (2 x 1Gbps) uplink between the switches. Even better, having multiple Ethernet ports in a LAG group provides not only increased bandwidth between switches, but also provides redundancy. If a single channel in the LAG group fails, the LAG bundle continues to carry traffic, albeit at a reduced rate.

Fortunately, it is very simple to create a LAG group between ports on the EX3200 switch, taking only four, easy steps:
  1. Create the virtual aggregated interface for the LAG group using the "set chassis aggregated-devices..." command (this will create a new interface, ae0, on the switch);
  2. Delete unit 0 in the interfaces that you want to bundle together;
  3. Use the "set interfaces...ether-options 802.3ad..." command to associate the physical interfaces that you want to aggregate with the virtual aggregated interface that you created in step 1; and
  4. Set the configuration options for the virtual aggregated interface with the "set interfaces...aggregated-ether-options..." and "set interfaces...family ethernet-switching" commands.
Let's set up a LAG group between ge-0/0/22 and ge-0/0/23 on two of our Juniper switches:

root@main3200# set chassis aggregated-devices ethernet device-count 1

[edit]
root@main3200# delete interfaces ge-0/0/22 unit 0

[edit]
root@main3200# delete interfaces ge-0/0/23 unit 0

[edit]
root@main3200# set interfaces ge-0/0/22 ether-options 802.3ad ae0

[edit]
root@main3200# set interfaces ge-0/0/23 ether-options 802.3ad ae0

[edit]
root@main3200# set interfaces ae0 aggregated-ether-options lacp active

[edit]
root@main3200# set interfaces ae0 unit 0 family ethernet-switching

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#
You now have a working LAG bundle between the switches, but if you try to ping from a host connected to one switch to a host connected on the other, you will find your pings failing with a "destination unreachable" error. Since you have multiple VLANs on the two switches, you will need to tag the VLANs on the aggregated Ethernet port, ae0, before hosts on the two switches can communicate with each other:

root@main3200# edit interfaces ae0 unit 0 family ethernet-switching

[edit interfaces ae0 unit 0 family ethernet-switching]
root@main3200# set port-mode trunk

[edit interfaces ae0 unit 0 family ethernet-switching]
root@main3200# set vlan members 20

[edit interfaces ae0 unit 0 family ethernet-switching]
root@main3200# set native-vlan-id default

[edit interfaces ae0 unit 0 family ethernet-switching]
root@main3200# commit
commit complete

[edit interfaces ae0 unit 0 family ethernet-switching]
root@main3200#


Now, connect a pair of Ethernet cables between the switches -- one from ge-0/0/22 on one switch to ge-0/0/22 on the second switch, and likewise for ge-0/0/23 -- and let's see if we can ping from a host on one switch to a host on the second switch:

me@myllt:~$ ping -c4 192.168.10.8
PING 192.168.10.8 (192.168.10.8) 56(84) bytes of data.
64 bytes from 192.168.10.8: icmp_req=1 ttl=64 time=0.795 ms
64 bytes from 192.168.10.8: icmp_req=2 ttl=64 time=0.502 ms
64 bytes from 192.168.10.8: icmp_req=3 ttl=64 time=0.519 ms
64 bytes from 192.168.10.8: icmp_req=4 ttl=64 time=0.501 ms

--- 192.168.10.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.501/0.579/0.795/0.125 ms
me@myllt:~$


Sweet! We have connectivity :) Now, let's see what happens when we pull an Ethernet cable:

me@myllt:~$ ping 192.168.10.8
PING 192.168.10.8 (192.168.10.8) 56(84) bytes of data.
64 bytes from 192.168.10.8: icmp_req=1 ttl=64 time=0.948 ms
64 bytes from 192.168.10.8: icmp_req=2 ttl=64 time=0.312 ms
64 bytes from 192.168.10.8: icmp_req=3 ttl=64 time=0.484 ms
64 bytes from 192.168.10.8: icmp_req=4 ttl=64 time=0.500 ms
64 bytes from 192.168.10.8: icmp_req=5 ttl=64 time=0.493 ms
64 bytes from 192.168.10.8: icmp_req=6 ttl=64 time=0.492 ms
64 bytes from 192.168.10.8: icmp_req=7 ttl=64 time=0.506 ms
64 bytes from 192.168.10.8: icmp_req=9 ttl=64 time=0.496 ms
64 bytes from 192.168.10.8: icmp_req=10 ttl=64 time=0.489 ms
64 bytes from 192.168.10.8: icmp_req=11 ttl=64 time=0.492 ms
64 bytes from 192.168.10.8: icmp_req=12 ttl=64 time=0.493 ms
64 bytes from 192.168.10.8: icmp_req=13 ttl=64 time=0.481 ms
64 bytes from 192.168.10.8: icmp_req=14 ttl=64 time=0.492 ms
64 bytes from 192.168.10.8: icmp_req=15 ttl=64 time=0.505 ms
^C
--- 192.168.10.8 ping statistics ---
15 packets transmitted, 14 received, 6% packet loss, time 13998ms
rtt min/avg/max/mdev = 0.312/0.513/0.948/0.129 ms
me@myllt:~$


Cool -- we only dropped one packet while the Junipers rerouted all of the traffic onto the good Ethernet link, and unlike STP/RSTP/MSTP, when both links are active, we can use all of the available bandwidth, rather than just a single 1Gbps link at a time.

Tuesday, November 12, 2013

JNCIA Lesson 7 -- DHCP

It is, perhaps, a little unfair that for many of these labs, I have been cheating slightly.

Don't get me wrong; I have configured all of the protocols and examples that we have discussed, and I have verified that the examples I have provided work as advertised. However, many of these examples have required that we connect one or more hosts to the various networks that we have built so that we can test end-to-end connectivity across the network(s). While there is certainly no reason why a network admin cannot configure such hosts by hand, I must confess that I do not like doing more work than is necessary. Again, do not be mislead; I am not claiming that I am unwilling to work when it is necessary, but rather I am saying that if there is an easy way to accomplish a task and a difficult way to accomplish a task, then, all else being equal, I will choose the easy way. To that end, when I have needed a PC connected to the Juniper switches to test connectivity, I have -- without providing you with the instructions on how to do likewise -- made use of the DHCP protocol to automatically assign IP addresses to my devices. I apologize, and in penance, I will endeavour to right that wrong in this lesson ;)

As I am sure you know -- or at least have by now guessed -- DHCP is a standard protocol for automatically assigning various network settings to computers on a LAN. Most obvious, of course, is the ability to automatically assign an IP address to a host on the network. However, DHCP can also assign a number of other settings such as the default gateway, DNS (name server) addresses, and domain name. Needless to say, the ability to automatically provision network settings to any device that connects to a LAN can be a huge time-saver for a busy network admin. Do you really want to visit the workstation of every user in your company first thing in the morning to assign an IP address for the day? Of course, not! Fortunately, this is another example of the kind of routine, mundane, repetitive task that computers perform extremely well, so let's set up our main office EX3200 to do so.

In one of the earlier lessons, we agreed that the default VLAN on our main3200 switch would use the network 192.168.1.0/24. However, we also stated that we would have a handful of network devices and servers on this network. Network devices almost always have their IP addresses assigned statically, as it becomes very difficult to configure your LAN equipment to reach a default gateway, for example, when the gateway address changes periodically. Servers, for exactly the same reason, often have statically assigned IP addresses also, and therefore, we will set aside the first 15 IP addresses -- 192.168.1.1 through 192.168.1.15 -- for servers and network equipment. Consequently, our DHCP server will assign addresses in the range 192.168.1.16 through 192.168.1.254 to client PCs. Also, our DNS servers for all three networks are located at 192.168.1.6 and 192.168.2.6; we'll assign those name server addresses to client PC's, as well. Let's get started:

root@main3200# edit system services

[edit system services]
root@main3200# set dhcp domain-name main.example.com

[edit system services]
root@main3200# set dhcp router 192.168.1.1

[edit system services]
root@main3200# set dhcp pool 192.168.1.0/24 address-range low 192.168.1.16 high 192.168.1.254

[edit system services]
root@main3200# set dhcp name-server 192.168.1.6

[edit system services]
root@main3200# set dhcp name-server 192.168.2.6

[edit system services]
root@main3200# commit
commit complete

[edit system services]
root@main3200#


That's it!

Now, hook up a PC to one of the ports in the default VLAN, and see if it obtains an address in the 192.168.1.0/24 net block:

me@myllt:~$ ip addr | egrep -A3 "eth0:"
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:24:e8:cb:f9:e9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.16/24 brd 192.168.1.255 scope global eth0
    inet6 fd04:4879:556a:0:24:e8ff:fecb:f9e9/64 scope global
me@myllt:~$


Sweet! My laptop obtained the IP address 192.168.1.16/24 automatically from the DHCP service on the EX3200 switch!

However, we still have a problem. If you recall, we had planned not just one, but two VLANs on this physical network: the default VLAN for hosts like my laptop, but also a Voice-over-IP VLAN for our internal PBX. It's nice not to have to statically assign IP addresses to desktops and laptops, but wouldn't it be nice to also have DHCP hand off IP addresses automatically to the VoIP telephones, too?

Fortunately, that's not a problem, either. All we have to do is set up a separate DHCP pool using the same net block that we put the VoIP VLAN into:

root@main3200# set dhcp router 192.168.10.1

[edit system services]
root@main3200# set dhcp pool 192.168.10.0/24 address-range low 192.168.10.8 high 192.168.10.254

[edit system services]
root@main3200# set dhcp sip-server address 192.168.10.2

[edit system services]
root@main3200# commit
commit complete

[edit system services]
root@main3200#


Now, to test, we'll connect another laptop to one of the ports in the VoIP VLAN and see if we get a 192.168.10.xxx address:

me@myllt2:~$ ip addr | egrep -A3 "eth0:"
2: eth0: mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:15:c5:08:5d:92 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.8/24 brd 192.168.10.255 scope global eth0
    inet6 fd04:4879:556a:0:15:c5ff:fe08:5d92/64 scope global
me@myllt2:~$


Yep, it worked! We now have both the default VLAN and the VoIP VLAN receiving IP addresses automatically.

It's outside of the scope of this lesson, but just for grins, let's see if OSPF will route across the VLANs for us:

me@myllt2:~$ ping -c1 192.168.1.16
PING 192.168.1.16 (192.168.1.16) 56(84) bytes of data.
64 bytes from 192.168.1.16: icmp_req=1 ttl=63 time=1.82 ms

--- 192.168.1.16 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.822/1.822/1.822/0.000 ms
me@myllt2:~$


There's that "routing-on-a-stick" we discussed earlier in action for ya' ;)

JNCIA Lesson 6 -- Spanning Tree, Rapid Spanning Tree and Multiple Spanning Tree

In our network design, we have two EX3200 switches at the main office, connected through a single copper cross-over cable. A savvy network administrator would probably look at our design and ask, "What would happen if either Ethernet port, or more likely, the Ethernet cable itself were to fail?" The link from our main3200 switch to our main2-3200 switch is indeed a single point of failure on our network. Many a junior network admin have had the sudden realization that such a design is a problem waiting to happen, and in their eagerness to show how pro-active and fore-sighted they are, have then run a second Ethernet cable between the two switches in order to create a redundant connection between them.

If the junior admin was lucky, (s)he probably just spent a while wondering why one of the redundant Ethernet ports suddenly went off-line (had a customer do that to me once, on a Metro-Ethernet ring, in fact). If the junior admin was not so lucky, however, (s)he created a broadcast storm, crashing the entire Layer-2 network with (her)his well-intentioned, but naive, blunder:



In actual practice, the diagrams above are an over-simplification: if Switch A was actually sending a broadcast, it would have forwarded the frame out the ports to *both* Switch B and Switch C, and both Switch B and Switch C would have forwarded the broadcast frame to each other, resulting in multiple copies of the same frame circulating through the network simultaneously. In fact, if there are four or more switches in the network connected in a full-mesh network, then with every cycle there are more and more frames circulating through the network until the switches can no longer keep up with traffic (with three or less switches, the number of frames circulating won't grow, since the switches will not forward a broadcast back out the interface upon which it was received).

In our example with the junior admin, (her)his instincts were good; the network, as originally designed, was vulnerable to failure, and it would be a good idea to design a redundant path between switches, if there were a way to prevent such loops from occurring. Fortunately, this is exactly the type of problem that the Spanning Tree protocol (STP), and it's later refinements, Rapid Spanning Tree (RSTP) and Muliple Spanning Tree (MSTP), were designed to solve.

The method through with STP prevents loops is quite simple: essentially, the protocol just shuts down redundant network ports until/unless the switches in the tree detect a failure on an active port. In our example above, and assuming that Switch A was the "root bridge" (we'll define that term shortly), Spanning Tree (or RSTP or MSTP) would put one of the ports on either Switch B or Switch C into a "blocking" state, thus breaking the loop. Now, if Switch A sends a broadcast frame to Switches B and C, they will each forward the packet to devices connected to their switch ports, but NOT to each other.

This (simplified) explanation of Spanning Tree raises an important question: how do the switches determine if there is a loop, or if there is a network port which needs to be shut down? When a switch (or group of switches) is first powered on, it sends a query out each of its enabled switch ports, called a "Bridge Protocol Data Unit." Routers and PCs ignore the BPDU, but other switches examine the BPDU to check for loops in the layer-2 topology. Some of the data transferred during this process is used to elect a "root bridge" -- the switch that will be the pinnacle of the spanning tree network. As we've already stated, spanning tree will shut down ports to break loops in the layer-2 network, but the root bridge is special: all enabled ports on the root bridge always remain active. On any switches with a single port connected to the root bridge, those ports will also always remain active, and are known as "root ports." If there are multiple ports to the root bridge, the switch will select a single port as a root port, and shut down the rest. Any ports that spanning tree uses to reach other switches, but which do not provide a path for that switch to reach the root bridge will are called "designated ports." Confused yet? Let's look a drawing to try to make it a little clearer:



As you can see, all of the switch ports that are directly connected to Switch A are root ports, all of the switch ports in a forwarding state that are NOT directly connected to Switch A are designated ports, and the ports in a blocking state are non-designated ports.

One other question that might come to mind at this point is, "how do the switches determine which switch is the root bridge?" Spanning Tree uses two metrics for electing a root bridge: first, the admin can set a value known as "root bridge priority" when configuring spanning tree, and lowest priority wins; second, if two or more switches have the same priority, then the switch with the lowest MAC address wins. In JunOS, the root bridge priority and MAC address are concatenated into a single value known as the "root ID" which can be shown with the "show spanning-tree bridge" command:

root@main3200# run show spanning-tree bridge

STP bridge parameters
Context ID                          : 0
Enabled protocol                    : RSTP
<...snip...>
  Local parameters
    Bridge ID                       : 32768.3c:8a:b0:99:df:c1
<...snip...>
root@main3200#


As you can see, the root ID on this switch is 32768.3c:8a:b0:99:df:c1. Suppose we had two other switches in a full-mesh, layer-2 network, and the other switches had root ID's of 32768.3c:8a:b0:99:e5:41 and 32768.3c:8a:b0:9a:22:01. Which switch would be elected root bridge? Let's connect these three switches together and find out! I'll connect ge-0/0/23 on the first switch to ge-0/0/22 on the second switch, connect ge-0/0/23 on the second switch to ge-0/0/22 on the third switch, then connect ge-0/0/23 on the third switch to ge-0/0/22 on the first switch. Once the switches are wired up to create a loop at layer-2, we'll re-run the "show spanning-tree bridge" command and see which switch was actually elected to be the root bridge:

root@main3200# run show spanning-tree bridge | match "Root ID"
  Root ID                           : 32768.3c:8a:b0:99:df:c1

[edit]
root@main3200#


root@branch1-3200# run show spanning-tree bridge | match "Root ID"
  Root ID                           : 32768.3c:8a:b0:99:df:c1

[edit]
root@branch1-3200#


root@branch2-3200# run show spanning-tree bridge | match "Root ID"
  Root ID                           : 32768.3c:8a:b0:99:df:c1

[edit]
root@branch2-3200#


Since all three switches have the same priority (JunOS' default of 32768), the election was determined by the lowest MAC address, which belongs to main3200.

If we wanted to know which ports were shut down, we would use the "show spanning-tree interface" command, but here, I have to make an admission: I couldn't actually find enough cross-over cables to connect all three switches in a full-mesh network, so I had to disconnect branch2-3200 for the following portion of the lab:

root@main3200# run show spanning-tree interface

Spanning tree interface parameters for instance 0

Interface    Port ID    Designated      Designated         Port    State  Role
                         port ID        bridge ID          Cost
ge-0/0/22.0    128:535      128:535  32768.3c8ab099dfc1     20000  FWD    DESG
ge-0/0/23.0    128:536      128:536  32768.3c8ab099dfc1     20000  FWD    DESG

[edit]
root@main3200#


root@branch1-3200# run show spanning-tree interface

Spanning tree interface parameters for instance 0

Interface    Port ID    Designated      Designated         Port    State  Role
                         port ID        bridge ID          Cost
ge-0/0/22.0    128:535      128:536  32768.3c8ab099dfc1     20000  BLK    ALT
ge-0/0/23.0    128:536      128:535  32768.3c8ab099dfc1     20000  FWD    ROOT

[edit]
root@branch1-3200#


If you notice, ge-0/0/22 on branch1-3200 is blocked by Spanning Tree, which shows that, when a link between two switches is determined to be redundant, if the path-cost back to the root bridge is equal, the lowest port number will be shut down (however, you can manually assign a port-cost to bias for or against a particular port, if you want).

RSTP is enabled on Juniper EX-series switches by default, but if you need to manually configure Spanning Tree, Rapid Spanning Tree or Multiple Spanning Tree, it's a very easy process. All three protocols are configured in exactly the same way, with just a couple of exceptions, which we'll cover in just a minute. Consequently, we'll only run through the configuration steps once, using RSTP. If you are using STP or MSTP, then rather than using "edit protocols rstp" (or "set protocols rstp ..."), you will use "edit protocols stp" or "edit protocols mstp" as appropriate.

First, we'll set the bridge priority to be lower on branch1-3200, to make it the root bridge instead of main3200:

root@branch1-3200# edit protocols rstp

[edit protocols rstp]
root@branch1-3200# set bridge-priority 20k

[edit protocols rstp]
root@branch1-3200#


Next, we will disable RSTP on ge-0/0/12.0 and commit the config:
root@branch1-3200# set interface ge-0/0/12.0 disable

[edit protocols rstp]
root@branch1-3200# commit
commit complete

[edit protocols rstp]
root@branch1-3200#


Now, one of the ports on main3200 should be in the blocking state, rather than on branch1-3200:

root@main3200# run show spanning-tree interface

Spanning tree interface parameters for instance 0

Interface    Port ID    Designated      Designated         Port    State  Role
                         port ID        bridge ID          Cost
ge-0/0/22.0    128:535      128:536  20480.3c8ab099e541     20000  BLK    ALT  
ge-0/0/23.0    128:536      128:535  20480.3c8ab099e541     20000  FWD    ROOT

[edit protocols rstp]
root@main3200#


...and sure enough, ge-0/0/22.0 on main3200 is now in the blocking state. Let's adjust the priority to put ge-0/0/23 in the blocking state, instead:

root@main3200# set interface ge-0/0/22 cost 1000

[edit protocols rstp]
root@main3200# commit
commit complete

[edit protocols rstp]
root@main3200# run show spanning-tree interface

Spanning tree interface parameters for instance 0

Interface    Port ID    Designated      Designated         Port    State  Role
                         port ID        bridge ID          Cost
ge-0/0/22.0    128:535      128:536  20480.3c8ab099e541      1000  FWD    ROOT
ge-0/0/23.0    128:536      128:535  20480.3c8ab099e541     20000  BLK    ALT  

[edit protocols rstp]
root@main3200#


One of the problems with spanning tree is the time it takes for the network to "converge" -- that is, the time it takes for the switches to elect a root bridge, determine if there are any loops in the topology, and then to shut down any redundant links. In STP, convergence can take almost a full minute, which is at least part of the reason RSTP was created. While RSTP is already quicker to converge than STP, it can converge even quicker if point-to-point links are declared as such with the "set protocols rstp interface ge-0/0/<whatever> mode point-to-point" command (Edit: if you are confused here, you are not alone. I'm not sure what a "point-to-point" link even means in a layer-2 network, but if I find out, I'll notate it here).

MSTP also differs from standard STP configuration in that you must add two more lines to the config:

root@main3200# set protocols mstp configuration-name jncia-example-1

[edit]
root@main3200# set protocols mstp msti 1 vlan [ 1 2 4 ]

[edit]
root@main3200# set protocols mstp msti 2 vlan [ 3 5 6 20 ]

[edit]
root@main3200#
<...etc...>


The only "gotcha" when putting VLANs into an MSTP instance (MSTI) is that every VLAN in a given instance must share a common topology.

Monday, November 11, 2013

JNCIA Lesson 5 -- VLANs

Up to this point, there has been an "elephant in the room" that we've carefully been sidestepping around. So far, many of our configs have referenced VLANs and Juniper's related -- but significantly different -- concept of "units." Today, we'll dig into VLANs and try to figure out exactly what they are and how to use them. We'll start with a common problem in networking that will hopefully illustrate the use and power of VLANs, then implement a solution for this problem in JunOS.

Suppose you have built a data network for your organization using standard Layer-2-only switches. Shortly afterwards, your internal PBX catastrophically fails beyond any hope of recovery. You decide that continuing to use antiquated POTS telephony is a poor idea, and instead, decide to implement an Asterisk open-source, voice-over-IP (VoIP) PBX system instead. Having done your homework, you are well aware of the common pitfalls associated with VoIP services -- such as Quality of Service (QoS), latency and jitter -- and therefore, you want to roll out the PBX on an entirely new network to minimize contention with other network consumers. However, it seems wasteful to buy additional switches for your enterprise, when you've already got unused ports on the switches you already have in use.

If only there were some way to logically separate the switch ports into separate networks, so that data users would only be in contention with each other for bandwidth while VoIP users could be on their own low-latency network...

Fortunately, this is exactly what VLANs were created to do. VLANs are a logical separation of two (or more) networks using the physical hardware of only one network. Remember when you were a kid and had to share a bedroom with brother or sister? Did you ever get into a fight with your sibling, and draw a line down the middle of the room, declaring something to the effect of, "This is my half of the room, and that is your half. Keep out of my half of the room!" That's basically all a VLAN does -- it splits the switch into separate broadcast domains so that traffic on one virtual LAN (VLAN) does not interact with traffic from other VLANs.

There are two ways for this split to occur, and typically, both methods will be used. First, you can separate the VLANs by port -- ports 1, 5, and 18-24 all belong to VLAN 10, while the remaining ports belong to VLAN 20, for example -- or you can separate traffic into separate VLANs by adding a tag into the Ethernet frame to mark certain frames as belonging to one VLAN and other frames as belonging to another VLAN. Each frame can belong to one and only one VLAN; there is no way to define a frame as belonging to multiple VLANs. Generally speaking, if the port will be connected to a client device -- a desktop, laptop, VoIP telephone, etc. -- you will define the VLAN by port, what is often referred to as an "untagged" or "access" VLAN port. On the other hand, if the port will be used to connect another network device, such as another switch or a router or sometimes even a server -- in other words, any time you potentially want more than one VLAN to transit an Ethernet link -- you will "tag" the frames coming from that port, creating a "tagged" or "trunk" port.

Let's take the example of the VoIP network and look at how we would implement such a design on the EX3200 switches. We've decided to use ports 0-7 on each EX3200 switch for the VoIP service because these ports support Power over Ethernet (PoE), which we can use to power the VoIP telephones (we'll just accept that statement as-is for the time being, as a full discussion of PoE is beyond the scope of this discussion). Additionally, we'll need a port for the Asterisk server, so we will add ge-0/0/8 to the VoIP VLAN, as well. We'll start the configuration by defining the Voice over IP VLAN on the switches:

root@main3200# edit vlans

[edit vlans]
root@main3200# set voip vlan-id 20

[edit vlans]
root@main3200#


Next, we need to define the VLAN interface:

root@main3200# top edit interfaces

[edit interfaces]
root@main3200# set vlan unit 20

[edit interfaces]
root@main3200#


If we wanted this VLAN to be routed, this is where we would add a Layer-3 address to the VLAN interface. Since we have three offices connected over a Layer-3 network, let's go ahead and add the IP address 192.168.10.1/24 to the main3200 router:

root@main3200# delete vlan unit 20 family ethernet-switching

[edit interfaces]
root@main3200# set vlan unit 20 family inet address 192.168.10.1/24

[edit interfaces]
root@main3200#


Now that we have defined the VLANs and the virtual interfaces through which the EX3200 will communicate, we'll need to assign these VLANs to the Gigabit Ethernet ports on the switch. The default VLAN is assigned to each switchport by, well, default. Therefore, we'll only need to add VLAN 20 the Ethernet ports that are used by the VoIP phones and PBX. We've already decided to put ge-0/0/0 through ge-0/0/8 into the VoIP VLAN, so let's make it so:

root@main3200# top

[edit]
root@main3200# set interfaces ge-0/0/0 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/1 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/2 unit 0 family ethernet-switching vlan members voips

[edit]
root@main3200# set interfaces ge-0/0/3 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/4 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/5 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/6 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/7 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# set interfaces ge-0/0/8 unit 0 family ethernet-switching vlan members voip

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


We now have nine Ethernet ports, ge-0/0/0 through ge-0/0/8 in the "voip" VLAN (VLAN 20). You hook up Linux hosts to two of the ports, connect a third Linux host to ge-0/0/10 (in the "default" VLAN), configure all of their IP addresses to all be in the 192.168.1.0/24 subnet, and start testing. As expected, hosts on ge-0/0/0 through ge-0/0/8 can talk to each other, but the host on ge-0/0/10 cannot reach either of the other two hosts, since it is in a different VLAN:

root@ge-0-0-2:/root# ping 192.168.1.238
PING 192.168.1.238 (192.168.1.238) 56(84) bytes of data.
64 bytes from 192.168.1.238: icmp_seq=1 ttl=64 time=0.436 ms
64 bytes from 192.168.1.238: icmp_seq=2 ttl=64 time=0.241 ms
64 bytes from 192.168.1.238: icmp_seq=3 ttl=64 time=0.234 ms
64 bytes from 192.168.1.238: icmp_seq=4 ttl=64 time=0.212 ms

--- 192.168.1.238 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.212/0.280/0.436/0.092 ms
root@ge-0-0-2:/root#
...
root@ge-0-0-10:~# nmap -sP 192.168.1.0/24

Starting Nmap 6.00 ( http://nmap.org ) at 2013-10-25 11:09 AKDT
Nmap scan report for 192.168.1.134
Host is up.
Nmap done: 256 IP addresses (1 host up) scanned in 11.12 seconds
root@ge-0-0-10:~# ip addr | egrep eth0 | egrep inet
inet 192.168.1.134/24 brd 192.168.1.255 scope global eth0
root@ge-0-0-10:~#
...
root@ge-0-0-6:~# ping -c4 192.168.1.134
PING 192.168.1.134 (192.168.1.134) 56(84) bytes of data.
From 192.168.1.238 icmp_seq=1 Destination Host Unreachable
From 192.168.1.238 icmp_seq=2 Destination Host Unreachable
From 192.168.1.238 icmp_seq=3 Destination Host Unreachable
From 192.168.1.238 icmp_seq=4 Destination Host Unreachable

--- 192.168.1.134 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3014ms
root@ge-0-0-6:~# ping -c4 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_req=1 ttl=64 time=1.96 ms
64 bytes from 192.168.1.1: icmp_req=2 ttl=64 time=0.176 ms
64 bytes from 192.168.1.1: icmp_req=3 ttl=64 time=0.164 ms
64 bytes from 192.168.1.1: icmp_req=4 ttl=64 time=0.165 ms

--- 192.168.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.164/0.617/1.965/0.778 ms
root@ge-0-0-6:~#


Perfect! Now, let's see if we can get ge-0/0/23 configured to do 802.1q tagging so we can use it as an uplink port from the second switch in the Main Office LAN:

root@main3200# edit interfaces ge-0/0/23 unit 0 family ethernet-switching

[edit interfaces ge-0/0/23 unit 0 family ethernet-switching]
root@main3200# set port-mode trunk

[edit interfaces ge-0/0/23 unit 0 family ethernet-switching]
root@main3200# set vlan members 20

[edit interfaces ge-0/0/23 unit 0 family ethernet-switching]
root@main3200# set native-vlan-id default

[edit interfaces ge-0/0/2 unit 0 family ethernet-switching]
root@main3200# commit
commit complete

[edit interfaces ge-0/0/2 unit 0 family ethernet-switching]
root@main3200#


Now, connect a cross-over cable between the two switches, and connect two hosts to each switch, one host (per switch) on ge-0/0/2 and one host (per switch) on ge-0/0/10. First we'll try pinging from a PC in the default VLAN on the first switch (main3200, ge-0/0/10) to all three other hosts:

root@mo-ge-0-0-10# ping -c4 mo2-ge-0-0-10.example.com
PING mo2-ge-0-0-10.example.com (192.168.1.134) 56(84) bytes of data.
64 bytes from 192.168.1.134: icmp_seq=1 ttl=64 time=0.590 ms
64 bytes from 192.168.1.134: icmp_seq=2 ttl=64 time=0.383 ms
64 bytes from 192.168.1.134: icmp_seq=3 ttl=64 time=0.363 ms
64 bytes from 192.168.1.134: icmp_seq=4 ttl=64 time=0.392 ms

--- mo2-ge-0-0-10.example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.363/0.432/0.590/0.091 ms
root@mo-ge-0-0-10/root# ping -c4 mo-ge-0-0-2.example.com
PING mo-ge-0-0-2.example.com (192.168.1.17) 56(84) bytes of data.
From 192.168.1.250 icmp_seq=1 Destination Host Unreachable
From 192.168.1.250 icmp_seq=2 Destination Host Unreachable
From 192.168.1.250 icmp_seq=3 Destination Host Unreachable
From 192.168.1.250 icmp_seq=4 Destination Host Unreachable

--- mo-ge-0-0-2.example.com ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 2999ms, pipe 3
root@mo-ge-0-0-10:/root# ping -c4 mo2-ge-0-0-2.example.com
PING mo2-ge-0-0-2.example.com (192.168.1.129) 56(84) bytes of data.
From 192.168.1.250 icmp_seq=1 Destination Host Unreachable
From 192.168.1.250 icmp_seq=2 Destination Host Unreachable
From 192.168.1.250 icmp_seq=3 Destination Host Unreachable
From 192.168.1.250 icmp_seq=4 Destination Host Unreachable

--- mo2-ge-0-0-2.example.com ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 2999ms, pipe 3
root@mo-ge-0-0-10:/root#


Exactly what I expected to see: the host on switch one, port ge-0/0/10 can ping the host on switch two, port ge-0/0/10, but cannot ping the hosts on ge-0/0/2 on either switch. Perfect! Let's make sure the hosts on ge-0/0/2 can ping each other but not hosts on ge-0/0/10:

root@mo-ge-0-0-2:/root# ping -c4 mo2-ge-0-0-10
PING mo2-ge-0-0-10 (192.168.1.134) 56(84) bytes of data.
From 192.168.1.17 icmp_seq=1 Destination Host Unreachable
From 192.168.1.17 icmp_seq=2 Destination Host Unreachable
From 192.168.1.17 icmp_seq=3 Destination Host Unreachable
From 192.168.1.17 icmp_seq=4 Destination Host Unreachable

--- mo2-ge-0-0-10 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 2999ms pipe 4
root@mo-ge-0-0-2:/root# ping -c4 mo2-ge-0-0-2
PING mo2-ge-0-0-2 (192.168.1.129) 56(84) bytes of data.
64 bytes from 192.168.1.129: icmp_req=1 ttl=64 time=0.509 ms
64 bytes from 192.168.1.129: icmp_req=2 ttl=64 time=0.233 ms
64 bytes from 192.168.1.129: icmp_req=3 ttl=64 time=0.247 ms
64 bytes from 192.168.1.129: icmp_req=4 ttl=64 time=0.283 ms

--- mo2-ge-0-0-2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.233/0.318/0.509/0.111 ms
root@mo-ge-0-0-2:/root# ping -c4 mo-ge-0-0-10
PING mo-ge-0-0-10 (192.168.1.250) 56(84) bytes of data.
From 192.168.1.17 icmp_seq=1 Destination Host Unreachable
From 192.168.1.17 icmp_seq=2 Destination Host Unreachable
From 192.168.1.17 icmp_seq=3 Destination Host Unreachable
From 192.168.1.17 icmp_seq=4 Destination Host Unreachable

--- mo-ge-0-0-10 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3015ms pipe 3
root@mo-ge-0-0-2:/root#


Again, that's exactly what I wanted to see! The hosts on ge-0/0/2 on both switches can ping each other, but can't ping hosts on ge-0/0/10. Since both VLANs are working properly across the uplink between the two switches, we know that VLAN 20 (VoIP) is being 802.1q tagged properly on ge-0/0/21, and the default VLAN (PCs and servers) is being carried as the native (untagged) VLAN on the same port.

Since the EX3200 contains routing code as well as switching code, we can configure our routing protocols to route from one VLAN to the other, if we choose:

root@main3200# show protocols ospf
export ospf-default;
area 0.0.0.0 {
    interface ge-0/0/21.0;
    interface vlan.0 {
        passive;
    }
    interface vlan.20 {
        passive;
    }
    interface ge-0/0/19.0 {
        passive;
    }
}

[edit]
root@main3200#


By placing both vlan.0 and vlan.20 into the OSPF process, the router will now route between the two VLAN interfaces (what is called, "Routing-on-a-Stick," or sometimes, a "one-armed router").

JNCIA Lesson 4 -- Routing Policies and Firewall Filters

There's a particularly corny scene in the movie "Firewall" where Harrison Ford's character takes over for a junior network admin when the bank he works for is being DoS'd -- or maybe it was just a brute-force password guessing attack, I can't remember now -- by an outside attacker. Peering intently at the screen, Ford thinks for a minute, then pecks out a sequence of commands on the screen, finishing with a smug, "That should hold them up for a while," to which the junior admin replies, "It would hold me up!" What makes the scene corny is that they catch just a second of the monitor on-camera, and I could see that Ford (or more likely, their technical consultant) had typed a simple Cisco access control list to block traffic from a specific source IP address. Any competent network admin can tell you that a serious attacker could easily repeat the attack from another address, and another, and another, ad infinitum, until the increasingly complex access control list alone causes as much trouble as the initial attack.

However, ACL's -- or Juniper's even more flexible and powerful firewall filters -- have a valid role in network security, and on JunOS, they provide for an even more mundane -- yet essential -- role in configuring dynamic routing. Let me start with a simple example: suppose you have a router at your main office location, with two branch offices connected through a private network provided by your service provider (Metro-Ethernet service, for example). You have multiple VLANs on each router which must be able to communicate with each VLAN on the other routers. The main office router has a single Internet connection to your upstream service provider. You want each of the branch office routers to be able to connect to the Internet through your main office router. When finished, the network should look something like this:



In the last lesson, we configured a simple network using OSPF to route between three LAN networks. This time, however, we have added a fourth route to our ISP. Generally, a small or even medium sized business doesn't share routes with their ISP. The ISP doesn't care about routes to your internal network (that's why RFC-1918 was created in the first place), nor does a typical small office router have enough memory or processing power to store the entire Internet's routing table (especially not if using RIP or OSPF, but that's a whole other topic we won't get into now). In fact, if you only have a single connection to your ISP, this is a perfect use for a static route. Router A, which is the only router connected to the upstream service provider, will have a static, default route. If only there were a way to share that route with routers B and C...

On a Cisco router, this would be a piece of cake: you would simply create the default route, then use the "default-information originate" command to tell OSPF to distribute the default route in your OSPF area. On a Juniper, it is (IMHO) more complicated than it needs to be, but it's not really THAT bad. First, just like a Cisco, we'll create the default route:

root@main3200# top

[edit]
root@main3200# set routing-options static route 0.0.0.0/0 next-hop 100.64.170.65

[edit]
root@main3200#


At this point, you should be able to ping onto the Internet (or to a test network beyond the "ISP" router) from Router A. However, from Router B or Router C, there is still no default route defined:

root@branch2-3200# run show route 172.16.0.1

[edit protocols ospf]
root@branch2-3200#


Next, we have to define a routing policy to redistribute this route into OSPF...:

root@main3200# set policy-options policy-statement ospf-default term 1 from route-filter 0.0.0.0/0 exact accept

[edit]
root@main3200#


...and then export that filter into OSPF:

root@main3200# set protocols ospf export ospf-default

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


If you try again from Router C...:

root@branch2-3200# run show route 172.16.0.1

inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0.0.0.0/0          *[OSPF/150] 00:01:16, metric 0, tag 0
                    > to 10.11.12.1 via ge-0/0/21.0

[edit protocols ospf]
root@branch2-3200#


Success!!! However, if you're like I was when I first figured this out, you are probably going, "That's the stupidest, most convoluted thing..."

Yeah, I get it, and I don't entirely disagree. Cisco and pretty much everyone else who makes the network gear that I've played with in the past assume that you *want* to share routes (that's what a router is for, after all, right?), and so their default policy is exactly that: when you enable a dynamic routing protocol, it's going to start advertising all the routes it can find, or at the very least, there will be switches ("default-information originate," "redistribute connected," "redistribute static," etc.) that turn on very broad swathes of networks with a single command. However, in such cases, it can be very easy to share more information than you intended, and in fact, can be rather difficult to filter out some of the networks that you don't want to share. JunOS, on the other hand, takes the exact opposite approach, and only shares routes that you explicitly tell the router that you want to share. From a security standpoint, I'd have to say the Juniper approach might -- just maybe -- be the better choice. And honestly, their filtering language is much more flexible and powerful than Cisco's ACL's, IMHO. So, enough with the sales pitch; let's dissect those commands and try to figure out exactly what they mean.

The first command we used was "set routing-options static route 0.0.0.0/0 next-hop 100.64.170.65" which is essentially telling the router, "if you don't know what route to take to reach a destination address, just send it to our default gateway at 100.64.170.65."

The last command was "set protocols ospf export ospf-default" which was telling the router that we want to export the routes defined in a route filter that we named "ospf-default" into our OSPF routing protocol. Again, pretty simple and straightforward.

The magic all happens in the second command, "set policy-options policy-statement ospf-default term 1 from route-filter 0.0.0.0/0 exact accept." There's a lot happening in this command, so let's dissect it a little further. In the first half, "set policy-options policy-statement ospf-default..." we are telling the router that we are going to create a filter, and that we want to name the filter "ospf-default." Next, we define the filter. A filter in JunOS can be a sequence of match-action statements, which is roughly analogous to "if-then" statements in a programming language. You can chain multiple statements together in JunOS to create complex, compound statements, just like you would in a programming language. We want to match basically any destination address, so the pseudo-code for what we want to accomplish looks more or less like this:

if destination-address matches 0.0.0.0/0 then
  forward the packet through the static route that matches the destination 0.0.0.0/0


Okay, that seems easy enough. What if we want to route anything matching 172.16.10.0/24 to one router, and route anything else to a second router? Let's try it. First, we'll configure a physical interface through which we will forward traffic:

root@main3200# set interfaces ge-0/0/19 unit 0 family ethernet-switching

[edit]
root@main3200# set interfaces ge-0/0/19 unit 0 family inet address 100.64.5.2/26

[edit]
root@main3200# show interfaces ge-0/0/19
unit 0 {
    family inet {
        address 100.64.5.2/26;
    }
}

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


I have connected a router to ge-0/0/19 on Router A to simulate another remote network (172.16.10.0/24) and connected a remote host on the outside interface of this router, using the IP address 172.16.10.20. On the outside interface of our "Internet" router, connected to ge-0/0/20, I have connected a host using the IP address 172.16.20.237. Connected to branch1-3200, I have a host using the IP address 192.168.2.32, and connected to branch1-3200, I have a host using the IP address 192.168.3.32. Right now, the two 192.168.x.32 hosts can ping each other, and the 172.16.20.237 host:

root@branch2-host1:~# ip addr | egrep -A3 eth0 | egrep "(eth0|inet) "
    inet 192.168.3.32/24 brd 192.168.3.255 scope global eth0
    inet 172.16.0.58/30 brd 172.16.0.59 scope global eth0.21
root@branch2-host1:~# ping -c1 192.168.2.32
PING 192.168.2.32 (192.168.2.32) 56(84) bytes of data.
64 bytes from 192.168.2.32: icmp_req=1 ttl=62 time=5.16 ms

--- 192.168.2.32 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 5.163/5.163/5.163/0.000 ms
root@branch2-host1:~# ping -c1 172.16.20.237
PING 172.16.20.237 (172.16.20.237) 56(84) bytes of data.
64 bytes from 172.16.20.237: icmp_req=1 ttl=61 time=1.34 ms

--- 172.16.20.237 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.342/1.342/1.342/0.000 ms
root@branch2-host1:~#


...and...:

me@branch1-host1:~$ ip addr | egrep eth0 | egrep "(eth0|inet) "
    inet 192.168.2.32/24 brd 192.168.2.255 scope global eth0
me@branch1-host1:~$ ping -c1 192.168.3.32
PING 192.168.3.32 (192.168.3.32) 56(84) bytes of data.
64 bytes from 192.168.3.32: icmp_req=1 ttl=62 time=2.93 ms

--- 192.168.3.32 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.936/2.936/2.936/0.000 ms
me@branch1-host1:~$ ping -c1 172.16.20.237
PING 172.16.20.237 (172.16.20.237) 56(84) bytes of data.
64 bytes from 172.16.20.237: icmp_req=1 ttl=61 time=1.51 ms

--- 172.16.20.237 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.510/1.510/1.510/0.000 ms
me@branch1-host1:~$


However, as of yet, there is no path to the host at 172.16.10.20:

root@branch2-host1:~# ping -c1 172.16.10.20
PING 172.16.10.20 (172.16.10.20) 56(84) bytes of data.
From 100.64.170.79 icmp_seq=1 Time to live exceeded

--- 172.16.10.20 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

root@branch2-host1:~#


...and...:

me@branch1-host1:~$ ping -c1 172.16.10.20
PING 172.16.10.20 (172.16.10.20) 56(84) bytes of data.
From 100.64.170.79 icmp_seq=1 Time to live exceeded

--- 172.16.10.20 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

me@branch1-host1:~$


This is expected, since we currently have a default route, redistributed through OSPF, from the main office router to both branch office routers. We now need to create a second route on the main office router to match 172.16.10.0/24, and redistribute it through OSPF to the branch office routers:

root@main3200# set routing-options static route 172.16.10.0/24 next-hop 100.64.5.1

[edit]
root@main3200# set policy-options policy-statement ospf-default term 2 from route-filter 172.16.10.0/24 exact accept

[edit]
root@main3200# set protocols ospf export ospf-default

[edit]
root@main3200#


We also need to tell the two branch routers how to reach the next-hop address of 100.64.5.1:

root@main3200# set protocols ospf area 0.0.0.0 interface ge-0/0/19.0 passive

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


...and now we have both a default route through the "ISP" through ge-0/0/20 and to the host on 172.16.10.20 through ge-0/0/19, shared with all three office locations.

Wednesday, November 6, 2013

JNCIA Lesson 3 -- Routing

Now that you've got your new EX3200 switches upgraded to the latest stable release, let's start working with the Layer-3 features of the switch. We'll start by reviewing a few basic concepts on how Juniper implements routing.

Juniper routers create two categories of databases while deciding how to forward packets from one network to another: the routing table and the forwarding table. The routing table is created by the routing engine, and contains the routes to various networks. The routing engine then copies the forwarding table to the packet forwarding engine, which uses the forwarding table to decide how to forward packets that come into the router.

Notice that I said JunOS creates two categories of databases. In truth, JunOS supports multiple routing instances, and therefore, multiple routing tables. If you run the "show route" command...:

root@main3200# run show route

inet.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
<...snip...>


...notice that it starts with the string, "inet.0." The inet.0 routing table is the default table for IPv4 routes. On some devices, you might also see...:

__juniper_private1__.inet.0


...which is a routing table used within JunOS to communicate with the router itself. There are also several other routing tables created by JunOS for various purposes:


There are two commands which are useful for troubleshooting routing and forwarding problems: "show route forwarding-table" and "show pfe route ip" (you can also use "show pfe route ipv6," "show pfe route mpls," and "show pfe route summary"). Since both of these commands produce a LOT of output, I won't show examples -- just go play with them :)

For a concise summary of the routes the router knows about, use the "show route" command:

root@main3200> show route

inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.11.12.0/30      *[Direct/0] 22:36:20
                    > via ge-0/0/21.0
10.11.12.1/32      *[Local/0] 22:36:29
                      Local via ge-0/0/21.0
100.64.170.79/32   *[Local/0] 22:36:29
                      Reject
192.168.1.0/24     *[Direct/0] 22:36:20
                    > via vlan.0
192.168.1.1/32     *[Local/0] 22:36:31
                      Local via vlan.0
192.168.2.0/24     *[OSPF/10] 22:35:32, metric 2
                    > to 10.11.12.2 via ge-0/0/21.0
192.168.10.0/24    *[Direct/0] 22:36:20
                    > via vlan.20
192.168.10.1/32    *[Local/0] 22:36:31
                      Local via vlan.20
224.0.0.5/32       *[OSPF/10] 22:36:32, metric 1
                      MultiRecv
224.0.0.22/32      *[IGMP/0] 22:36:32
                      MultiRecv         

root@main3200>


As you can see, this router already has been configured with routes to various networks. Some of these routes are created automatically, because the networks are directly connected to the router...:

10.11.12.0/30      *[Direct/0] 22:36:20
                    > via ge-0/0/21.0
10.11.12.1/32      *[Local/0] 22:36:29
                      Local via ge-0/0/21.0
...
192.168.1.0/24     *[Direct/0] 22:36:20
                    > via vlan.0
192.168.1.1/32     *[Local/0] 22:36:31
                      Local via vlan.0


...and some of these routes are known through Dynamic Routing Protocols:

192.168.2.0/24     *[OSPF/10] 22:35:32, metric 2
                    > to 10.11.12.2 via ge-0/0/21.0


I'll clear out the routing configurations on this router, and we'll start over with a very simple example: routing from this switch to a second EX3200 that we will call "branch3200", which will be connected with an Ethernet crossover cable:

root@main3200# delete routing-options

[edit]
root@main3200# delete protocols ospf

[edit]
root@main3200# delete policy-options

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


For the moment, don't worry too much about the meaning of each of those "delete..." statements. In short, all three statements were necessary to delete all of the routes and routing options that I had created on the switch earlier. By the end of this lesson, the reason for each of those "delete" statements should be clear :)

Back to routing...We will connect ge-0/0/21 on each switch via the crossover cable. Since routing occurs at Layer-3, we'll need to configure an IP address on each switch. I'll assume for now that you are familiar with the concept of subnetting a network; if you aren't, spend some quality time with Google before continuing with these lessons, as a lot of what we will be doing will require that you understand the concept. So, operating on that assumption, we'll create a /30 network between these two EX3200's, since we only need two IP addresses between them (one for each EX3200). I'll assign the IP address 10.11.12.1/30 to main3200 and 10.11.12.2/30 to branch3200:

root@main3200# delete interfaces ge-0/0/21 unit 0 family ethernet-switching

[edit]
root@main3200# set interfaces ge-0/0/21 unit 0 family inet address 10.11.12.1/30

[edit]
root@main3200#


...and...:

root@branch3200# delete interfaces ge-0/0/21 unit 0 family ethernet-switching

[edit]
root@branch3200# set interfaces ge-0/0/21 unit 0 family inet address 10.11.12.2/30

[edit]
root@branch3200#


At this point, we should be able to ping between the two switches:

root@main3200# run ping 10.11.12.2
PING 10.11.12.2 (10.11.12.2): 56 data bytes
64 bytes from 10.11.12.2: icmp_seq=0 ttl=64 time=5.879 ms
64 bytes from 10.11.12.2: icmp_seq=1 ttl=64 time=1.767 ms
^C
--- 10.11.12.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1.767/3.823/5.879/2.056 ms

[edit]
root@main3200#


Success! Since these two switches are directly connected across a single broadcast domain, we don't have to configure any routing at all to communicate over the 10.11.12.0/30 network. In Lesson 1 we configured a management IP address of 192.168.1.1/24 on interface vlan.0 on the main3200 switch. Let's assume that we have a mangement IP address of 192.168.2.1/24 on interface vlan.0 on the branch3200 switch. Can we ping from 192.168.1.1 to 192.168.2.1? Let's try it and see:

root@main3200# run ping 192.168.2.1
PING 192.168.2.1 (192.168.2.1): 56 data bytes
ping: sendto: No route to host
ping: sendto: No route to host
^C
--- 192.168.2.1 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

[edit]
root@main3200#


Nope! By default a router (or layer-3 switch, like the EX3200's we are using) only knows directly connected routes. In other words, main3200 only knows how to reach 10.11.12.0/30 and 192.168.1.0/24, and branch3200 only knows how to reach 10.11.12.0/30 and 192.168.2.0/24. Since both switches know how to reach 10.11.12.0/30, they can communicate with each other over this network, but since they don't have the 192.168.x.0/24 networks in common, main3200 can't reach 192.168.2.x, nor can branch3200 reach 192.168.1.x. However, we can fix that very easily:

root@main3200# set routing-options static route 192.168.2.0/24 next-hop 10.11.12.2

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


...and on the branch3200:

root@branch3200# set routing-options static route 192.168.1.0/24 next-hop 10.11.12.1

[edit]
root@branch3200# commit
commit complete

[edit]
root@branch3200#


Let's see how a ping from the main3200 switch to the management IP of the branch3200 switch works now:

root@main3200# run ping 192.168.2.1
PING 192.168.2.1 (192.168.2.1): 56 data bytes
64 bytes from 192.168.2.1: icmp_seq=0 ttl=64 time=2.043 ms
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=1.622 ms
^C
--- 192.168.2.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1.622/1.833/2.043/0.211 ms

[edit]
root@main3200#


Much better! With that one line of code, we told the main3200 switch that, in order to reach the 192.168.2.0/24 network, we had to talk to the router (we'll use "router" synonymously with layer-3 switch, from here on) at 10.11.12.2, and we told the branch3200 switch to talk to 10.11.12.1 to communicate with 192.168.1.0/24. Even better, the two end-point routers don't have to be directly connected for this to work. You can have an arbitrary number of routers between end-points (sort of -- more on this later) and, as long as each router has a next-hop for the destination network, you can "chain" routes together to reach your destination.

For example, suppose you had three routers, router A, router B and router C. Each router has a 192.168.x.1 management IP, 192.168.1.1 for router A, 192.168.2.1 for router B and 192.168.3.1 for router C. Router A is connected to router B on the 10.11.12.0/30 network, just as we've described with main3200 and branch3200 above. Router B is connected to router C on the 172.16.0.0/30 network. In that case, on router A, you would run the command "set routing-options static route 192.168.3.0/24 next-hop 10.11.12.2", just as we did before. On router B, you would run TWO commands, "set routing-options static route 192.168.3.0/24 next-hop 172.16.0.2" and "set routing-options static route 192.168.1.0/24 next-hop 10.11.12.1." On router C, you would run a single command again, "set routing-options static route 192.168.1.0/24 next-hop 172.16.0.1." If router A wanted to communicate with the 192.168.2.0/24 network on router B, then on router A you would also need to add "set routing-options static route 192.168.2.0/24 next-hop 10.11.12.2" as well, and if router C wanted to communicate with the 192.168.2.0/24 network on router B, you would have to add the command "set routing-options static route 192.168.2.0/24 next-hop 172.16.0.1" also. Instead of two commands for two routers, we now have eight commands for three routers -- that's an exponential growth (2^n, where n is the number of routers in the network) for full communication across the network. Clearly, if you have a small network, static routes are fine, but for large networks (where "large" doesn't really have to be all that large at all), creating static routes is a very time-consuming and error-prone proposition.

Fortunately, there's a solution for this problem. Very early on, router manufacturers decided that, while there were scenarios where statically routing between networks was appropriate, this was actually the kind of work that a computer -- and an average router is nothing more than a low-powered computer with very specific software and two or more network ports -- is very good at performing. Consequently, they developed dynamic routing protocols: algorithms that share routes between devices automatically, relieving the network administrator of the necessity of statically configuring all of the routes between various network devices.

One of the most common routing protocols in use is OSPF (Open Shortest Path First). Let's delete our static routes and replace them with a simple OSPF configuration:

root@main3200# top

[edit]
root@main3200# edit protocols ospf

[edit protocols ospf]
root@main3200# set area 0.0.0.0 interface ge-0/0/21.0

[edit protocols ospf]
root@main3200# set area 0.0.0.0 interface vlan.0 passive

[edit protocols ospf]
root@main3200# commit
commit complete

[edit protocols ospf]
root@main3200#


Now, let's see if our configuration works:

root@main3200# run show route protocol ospf    

inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.2.0/24     *[OSPF/10] 00:02:14, metric 2
                    > to 10.11.12.2 via ge-0/0/21.0
224.0.0.5/32       *[OSPF/10] 00:03:35, metric 1
                      MultiRecv

[edit protocols ospf]
root@main3200#


Perfect! We have a route to 192.168.2.0/24 on main3200.

One other tool that is useful for debugging OSPF routing problems is the "show ospf neighbor" command. Here is the output from immediately after committing the OSPF configuration. In particular, watch how the "State" changes as the two EX3200's begin to build the OSPF communications:

root@main3200# run show ospf neighbor
Address          Interface              State     ID               Pri  Dead
10.11.12.2       ge-0/0/21.0            2Way      10.11.12.2       128    39

[edit protocols ospf]
root@main3200# run show ospf neighbor          
Address          Interface              State     ID               Pri  Dead
10.11.12.2       ge-0/0/21.0            ExStart   10.11.12.2       128    33

[edit protocols ospf]
root@main3200# run show ospf neighbor          
Address          Interface              State     ID               Pri  Dead
10.11.12.2       ge-0/0/21.0            Full      10.11.12.2       128    36

[edit protocols ospf]
root@main3200#


In this sequence of captures, you can see the OSPF process begin establishing the OSPF adjacency with the neighbor router ("2Way"), exchanging routes with the neighbor ("ExStart") and fully converged ("Full"). If the routers don't move to the "Full" state after a couple of minutes, then something is wrong and you should make sure 1) that your configs are good, and 2) that you can ping from one router to the other. Once the state has changed to "Full", you can run the "show route protocol ospf" command to verify that all of the routes are being shared properly.

Let's discuss a couple of the statements in our OSPF configuration in a little more detail:

root@main3200# show
area 0.0.0.0 {
    interface ge-0/0/21.0;
    interface vlan.0 {
        passive;
    }
}

[edit protocols ospf]
root@main3200#


First, notice that all of our configuration statements fall under the "area 0.0.0.0" stanza. In OSPF, you can define multiple areas for OSPF to run in, although you always need an area 0.0.0.0 (sometimes shortened to "area 0" on some vendors' equipment, although Juniper will rewrite "area 0" as "area 0.0.0.0"). To understand areas, keep in mind that OSPF advertises routes within an area, so once a network becomes large, you can improve performance and reduce network overhead by segmenting your network into smaller subnetworks to reduce the number and size of advertisements. Area 0.0.0.0 is of particular importance because it is the "backbone network", that is, the portion of the network that connects all of the other areas (if any) together. In our case, the network is very small (just two switches), so we have put all of the networks in area 0.0.0.0.

Second, notice that under area 0.0.0.0, we have listed two interfaces, ge-0/0/21.0 and vlan.0. When we listed these interfaces, we told OSPF that we want to enable OSPF routing on these interfaces. For vlan.0, we further modified this statement by appending the "passive" parameter, which tells OSPF that, even though we want to make this interface part of the OSPF area, we don't want to form OSPF adjacencies through this interface.

That leaves us with one question remaining for this section: suppose we had multiple routes to a particular network, say one route that was defined statically, and another route to the same network that was defined through a dynamic routing protocol such as OSPF. Which patch would the router take to reach the destination? JunOS has predicted that such a scenario might occur, and has already addressed the issue through route preferences.

Basically, route preferences set a ranking of routes depending upon the way the route was derived. For example, directly connected routes are most preferable, statically defined routes are slightly less preferable, OSPF routes are even less preferable, RIP is less preferable than OSPF and BGP is the least preferable route of all (reference). These preferences aren't just academic, mind you. I once had to troubleshoot a routing problem with my upstream provider where I was experiencing a routing loop trying to reach a remote location from a second remote location in my network. My upstream provider spent several days claiming that he was advertising the proper routes through his core, until I finally asked him to check the static routing at one of the remote office locations. Since static routes are more preferable than dynamic routes, the old, incorrect static route was overriding the route he was advertising dynamically through his core, and was routing traffic to this one subnet back to my edge router, causing a loop.

This has only scratched the surface of routing on Juniper devices, but we'll save the more advanced topics for the next lesson.

Friday, November 1, 2013

JNCIA Lesson 2 -- Basic Operations

Now that you have basic management access configured on the EX3200 switch, you start connecting devices for testing. In particular, you want to get a feel for managing and monitoring the switch -- things like checking interface status, checking interface statistics, and monitoring system health. You also want to upgrade the firmware, since you noticed on Juniper's web site that there is an updated version of the firmware available.

Like a Cisco, you can view basic information about the network interfaces by typing "show interfaces" at the command prompt, or "show interfaces <interface name> to show a specific interface:

root@main3200> show interfaces ge-0/0/12
Physical interface: ge-0/0/12, Enabled, Physical link is Up
  Interface index: 141, SNMP ifIndex: 526
  Link-level type: Ethernet, MTU: 1514, Speed: Auto, Duplex: Auto,
  BPDU Error: None, MAC-REWRITE Error: None, Loopback: Disabled,
  Source filtering: Disabled, Flow control: Enabled, Auto-negotiation: Enabled,
  Remote fault: Online
  Device flags   : Present Running
  Interface flags: SNMP-Traps Internal: 0x0
  Link flags     : None
  CoS queues     : 8 supported, 8 maximum usable queues
  Current address: 3c:8a:b0:9a:22:0f, Hardware address: 3c:8a:b0:9a:22:0f
  Last flapped   : 2013-03-04 05:03:34 UTC (00:39:55 ago)
  Input rate     : 0 bps (0 pps)
  Output rate    : 0 bps (0 pps)
  Active alarms  : None
  Active defects : None
  Interface transmit statistics: Disabled

  Logical interface ge-0/0/12.0 (Index 77) (SNMP ifIndex 527)
    Flags: SNMP-Traps 0x0 Encapsulation: ENET2
    Bandwidth: 0
    Input packets : 1
    Output packets: 1353
    Protocol eth-switch
      Flags: None

root@main3200>


From this output, we can see that there is currently a device connected to ge-0/0/12 ("Physical link is Up"), that the interface is auto-negotiating speed and duplex ("Speed: Auto, Duplex: Auto"), that the port has been up for 39 minutes and 55 seconds ("Last flapped   : 2013-03-04 05:03:34 UTC (00:39:55 ago)"), and that there is currently no data flowing in or out of the interface ("Input rate     : 0 bps (0 pps)" and "Output rate    : 0 bps (0 pps)").

Like Cisco's IOS, JunOS supports the "show interfaces brief" command, but it doesn't work quite the same way:

root@main3200> show interfaces ge-0/0/0 brief
Physical interface: ge-0/0/0, Enabled, Physical link is Down
  Description: IP Phone
  Link-level type: Ethernet, MTU: 1514, Speed: Auto, Duplex: Auto,
  Loopback: Disabled, Source filtering: Disabled, Flow control: Enabled,
  Auto-negotiation: Enabled, Remote fault: Online
  Device flags   : Present Running
  Interface flags: Hardware-Down SNMP-Traps Internal: 0x0
  Link flags     : None

  Logical interface ge-0/0/0.0
    Flags: Device-Down SNMP-Traps 0x0 Encapsulation: ENET2
    eth-switch

root@main3200>


If you are familiar with IOS, "show interfaces terse" will provide output that is more like Cisco's "show ip interface brief" command:

root@main3200> show interfaces terse
Interface               Admin Link Proto    Local                 Remote
ge-0/0/0                up    down
ge-0/0/0.0              up    down eth-switch
ge-0/0/1                up    down
ge-0/0/1.0              up    down eth-switch
ge-0/0/2                up    down
ge-0/0/2.0              up    down eth-switch
ge-0/0/3                up    down
<...snip...>
vlan                    up    up
vlan.0                  up    up   inet     192.168.1.1/24  
vlan.20                 up    down inet     192.168.10.1/24

root@main3200>


If you want to view more verbose information about an interface, use "show interfaces detail"...:

root@main3200> show interfaces ge-0/0/20 detail
Physical interface: ge-0/0/20, Enabled, Physical link is Up
  Interface index: 149, SNMP ifIndex: 542, Generation: 152
  Link-level type: Ethernet, MTU: 1514, Speed: Auto, Duplex: Auto,
  BPDU Error: None, MAC-REWRITE Error: None, Loopback: Disabled,
  Source filtering: Disabled, Flow control: Enabled, Auto-negotiation: Enabled,
  Remote fault: Online
  Device flags   : Present Running
  Interface flags: SNMP-Traps Internal: 0x0
  Link flags     : None
  CoS queues     : 8 supported, 8 maximum usable queues
  Hold-times     : Up 0 ms, Down 0 ms
  Current address: 3c:8a:b0:9a:22:17, Hardware address: 3c:8a:b0:9a:22:17
  Last flapped   : 2013-03-04 06:19:44 UTC (00:03:50 ago)
  Statistics last cleared: Never
  Traffic statistics:
   Input  bytes  :                    0                    0 bps
   Output bytes  :                10346                  504 bps
   Input  packets:                    0                    0 pps
   Output packets:                  134                    0 pps
   IPv6 transit statistics:
    Input  bytes  :                   0
    Output bytes  :                   0
    Input  packets:                   0
    Output packets:                   0
  Egress queues: 8 supported, 4 in use
  Queue counters:       Queued packets  Transmitted packets      Dropped packets
    0 best-effort                    0                    0                    0
    1 assured-forw                   0                    0                    0
    5 expedited-fo                   0                    0                    0
    7 network-cont                   0                  134                    0
  Queue number:         Mapped forwarding classes
    0                   best-effort
    1                   assured-forwarding
    5                   expedited-forwarding
    7                   network-control
  Active alarms  : None
  Active defects : None
  Interface transmit statistics: Disabled

  Logical interface ge-0/0/20.0 (Index 85) (SNMP ifIndex 543) (Generation 150)
    Flags: SNMP-Traps 0x0 Encapsulation: ENET2
    Bandwidth: 0
    Traffic statistics:
     Input  bytes  :                    0
     Output bytes  :                15516
     Input  packets:                    0
     Output packets:                  134
    Local statistics:
     Input  bytes  :                    0
     Output bytes  :                15516
     Input  packets:                    0
     Output packets:                  134
    Transit statistics:
     Input  bytes  :                    0                    0 bps
     Output bytes  :                    0                    0 bps
     Input  packets:                    0                    0 pps
     Output packets:                    0                    0 pps
    Protocol eth-switch, Generation: 166, Route table: 0
      Flags: None

root@main3200>


Whew -- that's a lot of information! However, I don't see any information about input errors, carrier transitions, or even what the negotiated speed and duplex are. As it turns out, not only does JunOS have two levels of less verbose information beyond the standard "show interfaces;" JunOS also has two levels of more verbose information, as well. To see more information, use "show interfaces extensive" like so:

root@main3200> show interfaces ge-0/0/20 extensive
Physical interface: ge-0/0/20, Enabled, Physical link is Up
  Interface index: 149, SNMP ifIndex: 542, Generation: 152
  Link-level type: Ethernet, MTU: 1514, Speed: Auto, Duplex: Auto,
  BPDU Error: None, MAC-REWRITE Error: None, Loopback: Disabled,
  Source filtering: Disabled, Flow control: Enabled, Auto-negotiation: Enabled,
  Remote fault: Online
  Device flags   : Present Running
  Interface flags: SNMP-Traps Internal: 0x0
  Link flags     : None
  CoS queues     : 8 supported, 8 maximum usable queues
  Hold-times     : Up 0 ms, Down 0 ms
  Current address: 3c:8a:b0:9a:22:17, Hardware address: 3c:8a:b0:9a:22:17
  Last flapped   : 2013-03-04 06:19:44 UTC (00:31:25 ago)
  Statistics last cleared: Never
  Traffic statistics:
   Input  bytes  :                    0                    0 bps
   Output bytes  :                80309                  504 bps
   Input  packets:                    0                    0 pps
   Output packets:                 1064                    0 pps
   IPv6 transit statistics:
    Input  bytes  :                   0
    Output bytes  :                   0
    Input  packets:                   0
    Output packets:                   0
  Input errors:
    Errors: 0, Drops: 0, Framing errors: 0, Runts: 0, Policed discards: 0,
    L3 incompletes: 0, L2 channel errors: 0, L2 mismatch timeouts: 0,
    FIFO errors: 0, Resource errors: 0
  Output errors:
    Carrier transitions: 1, Errors: 0, Drops: 0, Collisions: 0, Aged packets: 0,
    FIFO errors: 0, HS link CRC errors: 0, MTU errors: 0, Resource errors: 0
  Egress queues: 8 supported, 4 in use
  Queue counters:       Queued packets  Transmitted packets      Dropped packets
    0 best-effort                    0                    0                    0
    1 assured-forw                   0                    0                    0
    5 expedited-fo                   0                    0                    0
    7 network-cont                   0                 1064                    0
  Queue number:         Mapped forwarding classes
    0                   best-effort
    1                   assured-forwarding
    5                   expedited-forwarding
    7                   network-control
  Active alarms  : None
  Active defects : None
  MAC statistics:                      Receive         Transmit
    Total octets                             0            80309
    Total packets                            0             1064
    Unicast packets                          0                0
    Broadcast packets                        0                0
    Multicast packets                        0             1064
    CRC/Align errors                         0                0
    FIFO errors                              0                0
    MAC control frames                       0                0
    MAC pause frames                         0                0
    Oversized frames                         0
    Jabber frames                            0
    Fragment frames                          0
    Code violations                          0
  Autonegotiation information:
    Negotiation status: Incomplete
    Local resolution:
        Local link Speed: 100 Mbps, Link mode: Half-duplex
  Packet Forwarding Engine configuration:
    Destination slot: 0
  CoS information:
    Direction : Output
    CoS transmit queue               Bandwidth               Buffer Priority   Limit
                              %            bps     %           usec
    0 best-effort            95       95000000    95             NA      low    none
    7 network-control         5        5000000     5             NA      low    none
  Interface transmit statistics: Disabled

  Logical interface ge-0/0/20.0 (Index 85) (SNMP ifIndex 543) (Generation 150)
    Flags: SNMP-Traps 0x0 Encapsulation: ENET2
    Bandwidth: 0
    Traffic statistics:
     Input  bytes  :                    0
     Output bytes  :               122696
     Input  packets:                    0
     Output packets:                 1064
    Local statistics:
     Input  bytes  :                    0
     Output bytes  :               122696
     Input  packets:                    0
     Output packets:                 1064
    Transit statistics:
     Input  bytes  :                    0                    0 bps
     Output bytes  :                    0                    0 bps
     Input  packets:                    0                    0 pps
     Output packets:                    0                    0 pps
    Protocol eth-switch, Generation: 166, Route table: 0
      Flags: None

root@main3200>


It's probably safe to say that if you can't find the interface information you need with the "show interfaces extensive" command, the information probably doesn't exist :) That's a lot of data, and it's easy to miss important information in the firehose. Try this instead:

root@main3200> show interfaces ge-0/0/20 extensive | find Autonegotiation
  Autonegotiation information:
    Negotiation status: Incomplete
    Local resolution:
        Local link Speed: 100 Mbps, Link mode: Half-duplex
  Packet Forwarding Engine configuration:
    Destination slot: 0
  CoS information:
    Direction : Output
    CoS transmit queue               Bandwidth               Buffer Priority   Limit
                              %            bps     %           usec
    0 best-effort            95       95000000    95             NA      low    none
    7 network-control         5        5000000     5             NA      low    none
  Interface transmit statistics: Disabled

  Logical interface ge-0/0/20.0 (Index 85) (SNMP ifIndex 543) (Generation 150)
    Flags: SNMP-Traps 0x0 Encapsulation: ENET2
    Bandwidth: 0
    Traffic statistics:
     Input  bytes  :                    0
     Output bytes  :               171146
---(more)---


Note that I edited the output slight to boldface the items I wanted to draw your attention to: "Negotiation status: Incomplete" and "Link mode: Half-duplex." Are there any input or output errors on the interface? Let's find out:

root@main3200> show interfaces ge-0/0/20 extensive | find "Input error" | match error
  Input errors:
    Errors: 0, Drops: 0, Framing errors: 0, Runts: 0, Policed discards: 0,
    L3 incompletes: 0, L2 channel errors: 0, L2 mismatch timeouts: 0,
    FIFO errors: 0, Resource errors: 0
  Output errors:
    Carrier transitions: 1, Errors: 0, Drops: 0, Collisions: 0, Aged packets: 0,
    FIFO errors: 0, HS link CRC errors: 0, MTU errors: 0, Resource errors: 0
    CRC/Align errors                         0                0
    FIFO errors                              0                0

root@main3200>


(Yes, that's right -- unlike IOS, you can chain filters together to form complex matching expressions, w00t!) In this case, I wanted to search for input or output errors, since the fact that Autonegotiation did not complete, and the interface is running at half-duplex tells me that I probably have one device auto-negotiating speed and duplex, and the other device hard-coded for speed and duplex (which, in fact, I have purposely done, just to show what happens). Typically, if one device is hard-coded for speed and duplex, while a connected device is auto-negotiating, they will match speeds, since the auto-negotiating side can sense the carrier frequency on the wire, and set speed appropriately. However, if it does not get a response to a request to negotiate duplex, it will fall back to the lowest common denominator, which is usually half-duplex. Unfortunately, if one side is using half-duplex while the other side is using full-duplex, you will get collisions on the wire, which will show up as errors on the Ethernet interface. In this case, there is not enough traffic on the line to have shown any errors yet.

Let's configure ge-0/0/20 to 100M, full-duplex to resolve the problem:

root@main3200> configure
Entering configuration mode

[edit]
root@main3200# edit interfaces ge-0/0/20

[edit interfaces ge-0/0/20]
root@main3200# set ether-options speed 100m

[edit interfaces ge-0/0/20]
root@main3200# set ether-options link-mode full-duplex

[edit interfaces ge-0/0/20]
root@main3200# commit
commit complete

[edit interfaces ge-0/0/20]
root@main3200# run show interfaces ge-0/0/20 terse
Interface               Admin Link
Proto    Local                 Remote
ge-0/0/20               up    down
ge-0/0/20.0             up    down eth-switch

[edit interfaces ge-0/0/20]
root@main3200#


Wait...what?!?! Why did the interface go up/down?

JunOS approaches auto-negotiation a little differently than most other vendors. On most network vendors' equipment, you can either hard-code speed and duplex, or you can negotiate speed and duplex with the link partner to whatever capabilities both partners can support. Technically, however, there is no reason a network device couldn't advertise a subset of the capabilities of its Ethernet interface, and that's exactly what JunOS does. When you set speed to 100Mbps and duplex to full, you are only telling JunOS to advertise 100M-Full on its Ethernet port. However, it is still auto-negotiating with its link partner. If you truly want to disable auto-negotiation, you have to explicitly tell JunOS to disable auto-negotiation:

root@main3200# set ether-options no-auto-negotiation

[edit interfaces ge-0/0/20]
root@main3200# commit
commit complete

[edit interfaces ge-0/0/20]
root@main3200# run show interfaces ge-0/0/20 terse
Interface               Admin Link
Proto    Local                 Remote
ge-0/0/20               up    up
ge-0/0/20.0             up    up   eth-switch

[edit interfaces ge-0/0/20]
root@main3200#


It's a little weird for someone used to other vendors' products, but it works :)

Two other commands worth experimenting with: "show interfaces statistics" (which you can further refine with the "terse" and "detail" filters, as in "show interfaces statistics detail") and "clear interfaces statistics." Both commands can have a specific interface listed, although JunOS is not consistent about where to put the interface spec:

root@main3200> show interfaces ge-0/0/20 statistics detail
Physical interface: ge-0/0/20, Enabled, Physical link is Up
<...snip...>
root@main3200> clear interfaces statistics ge-0/0/20

root@main3200>


If you want to view information about the EX3200 switch itself, JunOS provides the "show chassis ..." command:

root@main3200> show chassis ?
Possible completions:
  alarms               Show alarm status
  environment          Show component status and temperature, cooling system speeds
  firmware             Show firmware and operating system version for components
  fpc                  Show Flexible PIC Concentrator status
  hardware             Show installed hardware components
  lcd                  Show LCD display
  led                  Show LED status
  location             Show physical location of chassis
  mac-addresses        Show media access control addresses
  pic                  Show Physical Interface Card state, type, and uptime
  redundant-power-system  Show redundant power system chassis information
  routing-engine       Show Routing Engine status
  temperature-thresholds  Show chassis temperature threshold settings
root@main3200> show chassis environment
Class Item                           Status     Measurement
Power FPC 0 Power Supply 0           OK
      FPC 0 Power Supply 1           Absent
      FPC 0 Power Supply 2           Absent
      FPC 0 Power Supply 3           Absent
Temp  FPC 0 CPU                      OK         36 degrees C / 96 degrees F
      FPC 0 EX-PFE1                  OK         45 degrees C / 113 degrees F
      FPC 0 GEPHY Front Left         OK         35 degrees C / 95 degrees F
      FPC 0 GEPHY Front Right        OK         36 degrees C / 96 degrees F
      FPC 0 Uplink Conn              OK         32 degrees C / 89 degrees F
Fans  FPC 0 Fan 1                    OK         Spinning at normal speed

root@main3200>


Additionally, JunOS provides the "show system ..." command:

root@main3200> show system ?
Possible completions:
  alarms               Show system alarm status
  audit                Show file system MD5 hash and permissions
  autoinstallation     Show autoinstallation information
  boot-messages        Show boot time messages
  buffers              Show buffer statistics
  certificate          Show installed X509 certificates
  commit               Show pending commit requests (if any) and commit history
  configuration        Show configuration information
  connections          Show system connection activity
  core-dumps           Show system core files
  directory-usage      Show local directory information
  initialsetup         Show initial setup information
  license              Show feature licenses information
  login                Show system login state
  processes            Show system process table
  reboot               Show any pending halt or reboot requests
  rollback             Show rolled back configuration
  services             Show service applications information
  snapshot             Show snapshot information
  software             Show loaded JUNOS extensions
  statistics           Show statistics for protocol
  storage              Show local storage data
  subscriber-management  Show Subscriber management information
  uptime               Show time since system and processes started
  users                Show users who are currently logged in
  virtual-memory       Show kernel dynamic memory usage
root@main3200> show system uptime
Current time: 2013-03-04 08:10:26 UTC
System booted: 2013-03-01 13:30:13 UTC (2d 18:40 ago)
Protocols started: 2013-03-01 13:31:56 UTC (2d 18:38 ago)
Last configured: 2013-03-04 07:51:54 UTC (00:18:32 ago) by root
8:10AM  up 2 days, 18:40, 1 user, load averages: 0.00, 0.00, 0.00

root@main3200>


By this point, you are starting to feel pretty comfortable on the Juniper switch, so you decide to upgrade the firmware to the latest revision. You download the tarball onto an FTP server so you can upload it to your switch:

root@main3200> show version
Hostname: main3200
Model: ex3200-24t
JUNOS Base OS boot [11.4R7.5]
JUNOS Base OS Software Suite [11.4R7.5]
JUNOS Kernel Software Suite [11.4R7.5]
JUNOS Crypto Software Suite [11.4R7.5]
JUNOS Online Documentation [11.4R7.5]
JUNOS Enterprise Software Suite [11.4R7.5]
JUNOS Packet Forwarding Engine Enterprise Software Suite [11.4R7.5]
JUNOS Routing Software Suite [11.4R7.5]
JUNOS Web Management [11.4R7.5]
JUNOS FIPS mode utilities [11.4R7.5]

root@main3200> ftp 192.168.2.32
Connected to 192.168.2.32.
220 Authorized users only.
Name (192.168.2.32:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd vsftpd
250 Directory successfully changed.
ftp> ls *.tgz
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rwxr-xr-x    1 0        0        111506228 Nov 01 23:16 jinstall-ex-3200-12.3R4.6-domestic-signed.tgz
-rw-r--r--    1 1000     0        119235944 Nov 01 23:16 jinstall-ex-3200-13.2X50-D15.3-domestic-signed.tgz
226 Directory send OK.
ftp> get jinstall-ex-3200-12.3R4.6-domestic-signed.tgz /var/tmp/jinstall-ex-3200-12.3R4.6-domestic-signed.tgz
local: /var/tmp/jinstall-ex-3200-12.3R4.6-domestic-signed.tgz remote: jinstall-ex-3200-12.3R4.6-domestic-signed.tgz
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for jinstall-ex-3200-12.3R4.6-domestic-signed.tgz (111506228 bytes).
100% |**************************************************|   106 MB    00:00 ETA
226 Transfer complete.
111506228 bytes received in 40.55 seconds (2.62 MB/s)
ftp> quit
221 Goodbye.

root@main3200> file list /var/tmp/

/var/tmp/:
.snap/
ex_autod_config
ex_autod_rollback_cfg
gres-tp/
jinstall-ex-3200-12.3R4.6-domestic-signed.tgz
krt_gencfg_filter.txt
rtsdb/

root@main3200> request system software validate /var/tmp/jinstall-ex-3200-12.3R4.6-domestic-signed.tgz

root@main3200> request system software add /var/tmp/jinstall-ex-3200-12.3R4.6-domestic-s
NOTICE: Validating configuration against jinstall-ex-3200-12.3R4.6-domestic-signed.tgz.
NOTICE: Use the 'no-validate' option to skip this if desired.
WARNING: A reboot is required to install the software
WARNING:     Use the 'request system reboot' command immediately


root@main3200> request system reboot
Reboot the system ? [yes,no] (no) yes

Shutdown NOW!
[pid 7419]

root@main3200>
*** FINAL System shutdown message from root@main3200 ***

System going down IMMEDIATELY


At this point you can go make a coffee, go make a sandwich, meet a nice girl, raise a family, retire...whatever. It's going to take a while for the switch to reboot :) Eventually, however, you will be greeted with the following message:

main3200 (ttyu0)

login: root
Password:

--- JUNOS 12.3R4.6 built 2013-09-13 02:39:14 UTC


root@main3200:LC:0%


Woohoo! You are now running JunOS 12.3R4.6! Just to be sure, you can run the "show version" command again:

root@main3200:LC:0% cli
root@main3200> show version
Hostname: main3200
Model: ex3200-24t
JUNOS Base OS boot [12.3R4.6]
JUNOS Base OS Software Suite [12.3R4.6]
JUNOS Kernel Software Suite [12.3R4.6]
JUNOS Crypto Software Suite [12.3R4.6]
JUNOS Online Documentation [12.3R4.6]
JUNOS Enterprise Software Suite [12.3R4.6]
JUNOS Packet Forwarding Engine Enterprise Software Suite [12.3R4.6]
JUNOS Routing Software Suite [12.3R4.6]
JUNOS Web Management [12.3R4.6]
JUNOS FIPS mode utilities [12.3R4.6]

root@main3200>


One step left in the upgrade: JunOS provides a snapshot of the old image, so the OS can fail over to the previous version if there is a problem with the new version. Once you know the new OS is working, you need to remove the old version or you may find yourself (not that I would know, *cough*) running the old OS again at some point:

root@main3200> request system snapshot slice alternate
Formatting alternate root (/dev/da0s1a)...
Copying '/dev/da0s2a' to '/dev/da0s1a' .. (this may take a few minutes)
The following filesystems were archived: /

root@main3200>


...and you're done (and yes, it does take a "few" minutes...and maybe a few minutes longer than that, even [:roll_eyes:]).

All that's left for today is password recovery, which is a pretty simple process. Power off the switch, and, with a console cable connected between the console port on the switch and the serial port on a PC or laptop, watch the boot process until you see the following prompt:

Hit [Enter] to boot immediately, or space bar for command prompt.
Booting [/kernel] in 1 second...


Press the space bar when you see this prompt, then when the system prompts you, type...:

Type '?' for a list of commands, 'help' for more detailed help. loader> boot -s


The switch will dump some more log messages to the screen as it starts the requested boot sequence, then will display the following message:

Enter full pathname of shell or 'recovery' for root password recovery or RETURN for /bin/sh:

Type "recovery" and hit the enter key. When the switch finally finishes booting, just follow the on-screen instructions...:

NOTE: Once in the CLI, you will need to enter configuration mode using
NOTE: the 'configure' command to make any required changes. For example,
NOTE: to reset the root password, type:
NOTE:    configure
NOTE:    set system root-authentication plain-text-password
NOTE:    (enter the new password when asked)
NOTE:    commit
NOTE:    exit
NOTE:    exit
NOTE: When you exit the CLI, you will be asked if you want to reboot
NOTE: the system

Starting CLI ...
root@main3200> configure
Entering configuration mode

[edit]
root@main3200# set system root-authentication plain-text-password
New password:
Retype new password:

[edit]
root@main3200# commit
commit complete

[edit]
root@main3200#


Reboot the system, and you are done!