| 1 | % Anycast lab |
|---|
| 2 | |
|---|
| 3 | **Anycast service configuration** |
|---|
| 4 | |
|---|
| 5 | We are going to create a class-wide anycast resolver infrastructure. |
|---|
| 6 | |
|---|
| 7 | The goal is to configure your resolver to respond to an anycast |
|---|
| 8 | IP address (here: 20.20.20.20/32), and use an IGP (OSPF) to |
|---|
| 9 | announce availability of this IP on the local network. |
|---|
| 10 | |
|---|
| 11 | # Host configuration - on your `resolv` server |
|---|
| 12 | |
|---|
| 13 | The host configuration is detailed below. |
|---|
| 14 | |
|---|
| 15 | ## Creating looppback |
|---|
| 16 | |
|---|
| 17 | Start by creating a new interface on your host, called `lo1`. |
|---|
| 18 | |
|---|
| 19 | $ sudo ifconfig lo1 create |
|---|
| 20 | |
|---|
| 21 | ## Anycast address |
|---|
| 22 | |
|---|
| 23 | we're going to assign the anycast address to be used in the classroom |
|---|
| 24 | (20.20.20.20) to this interface: |
|---|
| 25 | |
|---|
| 26 | $ sudo ifconfig lo1 20.20.20.20/32 |
|---|
| 27 | |
|---|
| 28 | Note: to make this permanent, we'd add the following lines to |
|---|
| 29 | `/etc/rc.conf`: |
|---|
| 30 | |
|---|
| 31 | cloned_interfaces="lo1" |
|---|
| 32 | ifconfig_lo1="20.20.20.20/32" |
|---|
| 33 | |
|---|
| 34 | Test that you can ping this IP locally: |
|---|
| 35 | |
|---|
| 36 | $ ping 20.20.20.20 |
|---|
| 37 | |
|---|
| 38 | ## Enabling the routing daemon |
|---|
| 39 | |
|---|
| 40 | We now need to enable OSPF on this host, so that it will announce |
|---|
| 41 | the prefix (20.20.20.20/32) into the network. |
|---|
| 42 | |
|---|
| 43 | We'll use Quagga (http://www.nongnu.org/quagga/) for this. |
|---|
| 44 | |
|---|
| 45 | To enable the routing control daemon (zebra) and the OSPF daemon (`ospfd`), |
|---|
| 46 | add the following lines to `/etc/rc.conf`: |
|---|
| 47 | |
|---|
| 48 | quagga_daemons="ospfd zebra" |
|---|
| 49 | quagga_enable="YES" |
|---|
| 50 | |
|---|
| 51 | Configure quagga: |
|---|
| 52 | |
|---|
| 53 | $ cd /usr/local/etc/quagga |
|---|
| 54 | $ sudo touch ospfd.conf zebra.conf |
|---|
| 55 | $ sudo chown quagga * |
|---|
| 56 | $ ls -l |
|---|
| 57 | |
|---|
| 58 | Start the routing services: |
|---|
| 59 | |
|---|
| 60 | $ sudo service quagga start |
|---|
| 61 | $ ps ax | grep ospfd |
|---|
| 62 | $ ps ax | grep zebra |
|---|
| 63 | |
|---|
| 64 | ## Configuring OSPF to announce the IP |
|---|
| 65 | |
|---|
| 66 | The quagga `vtysh` connects you to the Quagga command line interface, |
|---|
| 67 | which is very similar to Cisco IOS. |
|---|
| 68 | |
|---|
| 69 | $ sudo vtysh |
|---|
| 70 | |
|---|
| 71 | You should now be presented with a prompt similar to this: |
|---|
| 72 | |
|---|
| 73 | resolv.grpXX.dns.nsrc.org# |
|---|
| 74 | |
|---|
| 75 | Enter configuration mode: |
|---|
| 76 | |
|---|
| 77 | # conf terminal |
|---|
| 78 | |
|---|
| 79 | You should now see: |
|---|
| 80 | |
|---|
| 81 | resolv.grpXX.dns.nsrc.org(config)# |
|---|
| 82 | |
|---|
| 83 | Let's configure OSPF: |
|---|
| 84 | |
|---|
| 85 | # router ospf |
|---|
| 86 | # ospf router-id 10.10.x.3 |
|---|
| 87 | # network 10.10.0.0/16 area 0 |
|---|
| 88 | # network 20.20.20.20/32 area 0 |
|---|
| 89 | # exit |
|---|
| 90 | # exit |
|---|
| 91 | # write mem |
|---|
| 92 | |
|---|
| 93 | # Reconfigure unbound |
|---|
| 94 | |
|---|
| 95 | Unbound needs to be told to use the right address for the reply. |
|---|
| 96 | |
|---|
| 97 | Edit the file `/usr/local/etc/unbound/unbound.conf`, and in the |
|---|
| 98 | server category, add the following statement: |
|---|
| 99 | |
|---|
| 100 | interface-automatic: yes |
|---|
| 101 | |
|---|
| 102 | Save the file and exit, then restart unbound: |
|---|
| 103 | |
|---|
| 104 | # service unbound restart |
|---|
| 105 | |
|---|
| 106 | Note: this is required to make sure that the source IP address Unbound will |
|---|
| 107 | use to replying to the client, is the same that it received the request on. |
|---|
| 108 | |
|---|
| 109 | # Router configuration (this is done by the instructor) |
|---|
| 110 | |
|---|
| 111 | The instructor will configure a router to listen to the OSPF announcements, |
|---|
| 112 | and on the projector we'll look as the different groups configure the anycast |
|---|
| 113 | address, and the OSPF routing table is updated. |
|---|
| 114 | |
|---|
| 115 | As the class progresses, the instructor will update the OSPF view on the |
|---|
| 116 | projector: |
|---|
| 117 | |
|---|
| 118 | ~~~ |
|---|
| 119 | *> 20.20.20.20/32, Intra, cost 11, area 0 |
|---|
| 120 | via 10.10.15.1, FastEthernet0/0 |
|---|
| 121 | via 10.10.20.3, FastEthernet0/0 |
|---|
| 122 | ~~~ |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | ## Testing anycast! |
|---|
| 126 | |
|---|
| 127 | On your OSPF process, run the following commands (use `sudo vtysh`) |
|---|
| 128 | |
|---|
| 129 | # show ip route ospf |
|---|
| 130 | |
|---|
| 131 | You will only see your own route (directly connected), being advertised |
|---|
| 132 | to the world: |
|---|
| 133 | |
|---|
| 134 | ~~~ |
|---|
| 135 | O 10.10.0.0/16 [110/10] is directly connected, eth0, 00:04:35 |
|---|
| 136 | O 20.20.20.20/32 [110/10] is directly connected, lo1, 00:04:35 |
|---|
| 137 | ~~~ |
|---|
| 138 | |
|---|
| 139 | Now, it's time to use this anycast platform we have built. |
|---|
| 140 | |
|---|
| 141 | From one of your servers (auth or resolv), run the following command: |
|---|
| 142 | |
|---|
| 143 | dig @20.20.20.20 www.YOURTLD |
|---|
| 144 | |
|---|
| 145 | If everything goes well, you will be getting the answer - however, |
|---|
| 146 | we don't know which server answered. |
|---|
| 147 | |
|---|
| 148 | To find out, let's analyze the traffic as it arrives on your servers. |
|---|
| 149 | |
|---|
| 150 | We will do this in class, using tcpdump and ping. |
|---|
| 151 | |
|---|
| 152 | In a new window, on your resolver, run tcpdump: |
|---|
| 153 | |
|---|
| 154 | $ sudo tcpdump -n -i eth0 port 53 or icmp |
|---|
| 155 | |
|---|
| 156 | Let the instructor know when you have done this. |
|---|
| 157 | |
|---|
| 158 | We will then proceed to: |
|---|
| 159 | |
|---|
| 160 | - ping 20.20.20.20 - who in the class is receiving the traffic ? |
|---|
| 161 | - run `dig @20.20.20.20 www.YOURTLD` - same question as above |
|---|
| 162 | |
|---|
| 163 | Observe the sequence numbers in the tcpdump output. |
|---|
| 164 | |
|---|
| 165 | You can run these tests yourself: |
|---|
| 166 | |
|---|
| 167 | - ping and dig to 20.20.20.20 from another server in the class - one |
|---|
| 168 | NOT configured to run the anycast service. |
|---|
| 169 | |
|---|
| 170 | - Use traceroute (or mtr -n) to 20.20.20.20 and see the path followed. |
|---|
| 171 | |
|---|
| 172 | ## Identifying the DNS server |
|---|
| 173 | |
|---|
| 174 | As shown in class, use this command to identify which server |
|---|
| 175 | you are talking to: |
|---|
| 176 | |
|---|
| 177 | $ dig @20.20.20.20 hostname.bind txt chaos |
|---|
| 178 | |
|---|
| 179 | # Optional |
|---|
| 180 | |
|---|
| 181 | ## Service monitoring |
|---|
| 182 | |
|---|
| 183 | The problem with the above setup is that if the Unbound server dies |
|---|
| 184 | or otherwise stops responding, DNS queries to that host will go |
|---|
| 185 | unanswered. One way to ensure that this doesn't happen, is to remove |
|---|
| 186 | the OSPF prefix announcement, should the service fail. |
|---|
| 187 | |
|---|
| 188 | A simple way to do this would be to run a check that periodically |
|---|
| 189 | checks the DNS service for availability, and would terminate the |
|---|
| 190 | Quagga processes (thus stopping the OSPF announcement). |
|---|
| 191 | |
|---|
| 192 | In shellscript, we'd do something like: |
|---|
| 193 | |
|---|
| 194 | ~~~ |
|---|
| 195 | #!/bin/sh |
|---|
| 196 | |
|---|
| 197 | while true |
|---|
| 198 | do |
|---|
| 199 | dig +short @20.20.20.20 some.hostname.to.lookup | wc -l |
|---|
| 200 | if [ $? -eq 0 ]; then |
|---|
| 201 | # If dig returns 0 lines, we have not found a record - |
|---|
| 202 | # something is wrong! |
|---|
| 203 | killall zebra |
|---|
| 204 | kilall ospfd |
|---|
| 205 | fi |
|---|
| 206 | done |
|---|
| 207 | ~~~ |
|---|
| 208 | |
|---|
| 209 | This is overly simple, and there are a number of things we could |
|---|
| 210 | improve: |
|---|
| 211 | |
|---|
| 212 | - this doesn't deal with timeouts / slow servers. We could time the |
|---|
| 213 | query, and if it takes longer than, say, 500ms, and/or dig exits |
|---|
| 214 | with a timeout code (error code 9), then we could decide to terminate |
|---|
| 215 | OSPF |
|---|
| 216 | |
|---|
| 217 | - we could consider restarting the nameserver as well, and then |
|---|
| 218 | restarting OSPF |
|---|
| 219 | |
|---|
| 220 | ## Anycast authoritative service |
|---|
| 221 | |
|---|
| 222 | What about BIND ? Can you, in collaboration with your secondaries |
|---|
| 223 | in the class, create anycast services for your TLDs ? You'll have |
|---|
| 224 | to pick a different IP (20.20.20.X/32) for each of your domains. |
|---|
| 225 | |
|---|
| 226 | Tell the instructor which IP you picked. |
|---|
| 227 | |
|---|
| 228 | ## Security - OSPF authentication |
|---|
| 229 | |
|---|
| 230 | Is it a good idea to let anyone announce prefixes on your infrastructure |
|---|
| 231 | network ? What would you do to limit who would be allowed to announce |
|---|
| 232 | an anycast prefix on your server network ? |
|---|
| 233 | |
|---|