How to perform WHOIS lookups on uncommon TLDs

What is WHOIS?

WHOIS is a standard/protocol that was created with one of the purposes being the storage of information on the ownership of a specific domain. If you need to know who owns a domain or how to contact them, you can query a hosted WHOIS database by submitting a request to one of the WHOIS servers responsible for serving the owner information for a specific TLD (Top Level Domain). Examples of common TLDs are .com, .net, .org. There are also designated country TLDs and TLDs for other purposes. You can see a detailed list on Wikipedia.

You can perform WHOIS lookups via online web utilities or more commonly, through the use of the Unix JWhois client, which comes installed on most Linux distributions and OS X. If you would like to use the client and primarily use Windows, you can use Cygwin and choose the 'whois' package as part of the installation process.

How does my client know what WHOIS server to query?

For the most part, the client knows which server to use based on static configuration, where each TLD has a server to perform WHOIS lookups towards. For JWhois, there would be a block of configuration in the jwhois.conf global configuration file under the whois-servers section, where you specify the TLD(s) using regular expressions followed by the given server for that TLD match. Examples:

"\\.com$" = "whois.verisign-grs.com";
"\\.edu$" = "whois.educause.edu";
"\\.gov$" = "whois.nic.gov";

However, with the increasing number of TLDs, it is not scalable to have all these mappings in a local configuration file. Of course, the client fails back to a default WHOIS server to query, in case there is no mapping for a given uncommon TLD but this will fail if the information requested does not exist on that server. So for a new TLD, WHOIS lookups for that TLD will likely fail on any fresh whois installation and most online WHOIS web clients out there without manual WHOIS server specification.

Querying uncommon TLDs

Luckily the JWhois client allows you to also specify the server that you want to query for a given lookup but you would need to know of this server beforehand. The Internet Assigned Numbers Authority (IANA) maintains a database of information for each TLD, served conveniently to you on this web page. Each page will give you a load of information on that specific TLD, including the WHOIS server. So querying a specific domain name using the Unix JWhois client would look like this for the 'bingo' TLD (using the -h flag to specify a specific WHOIS server):

$ whois -h whois.donuts.co example.bingo
[Querying whois.donuts.co]
(.. Omitting query results ..)

One step further: automating the WHOIS server lookup

When browsing the IANA Root Zone Database, I noticed that the URIs for all of the TLDs used the same format; "/domains/root/db/(TLD_HERE).html". This allows for easy web scraping, using a simple script.

I wrote a Python script, 'Phois', that takes a domain argument as JWhois does. However unlike JWhois which checks the domain name against its configuration file for the WHOIS server, Phois strips the TLD from the query, caches the IANA page for that TLD, scrapes the WHOIS server from there, then performs a normal WHOIS lookup but by specifying the WHOIS server to perform the lookup on. You can find this Phois script on my GitHub and can simply git clone it and pip install. Alternatively, you can throw it in your "/usr/bin" directory or another executable directory in the $PATH on your machine as long as you have the Python pre-reqs installed (don't forget to make the script executable; chmod +x). It works like so:

$ phois watermelon.ninja
[Querying whois.unitedtld.com]
[whois.unitedtld.com]
(.. Omitting query results ..)

Let me know what you think!

Intro to IPv6 BGP peering

It's no bluff that IPv6 has been standardized for nearly two decades (RFC 2460). There has been close to zero percent adoption up until about 3-4 years ago where you can see some of the early adopters are getting their feet wet; Google Statistic shows climb from 2% to 18% in the past three years, by analyzing it's users' request origin. IPv6 BGP route table size is also up to 39k, per cidr-report.org.

Although it may look a bit daunting at first, it is actually quite simple to get started. You can start off by contacting your ISP to see if they can provide IPv6 service on your circuit, in which they will usually provide you a several /64 (for transit and internal usage) or a larger range, depending on your size and business needs. If you prefer to have your own PI space, you can request a prefix through ARIN (or your regions RIR); generally from what I've seen, you can get anywhere from a /56 at a small business, to a /40 for a medium enterprise, to a /32 for a large enterprise or small ISP and even larger from there. If your ISP doesn't support IPv6 and you would still like to play around with it, don't fret, you can utilize an IPv6 broker such as Hurricane Electric

Once you are ready to peer with your provider or IPv6 broker, here is a simple guide on how to configure your side of the connection

1. First step would be to check if your device/license supports both IPv6 and BGP. For Cisco, you can check this using their Feature Navigator. For my example, I am using a Cisco 3560, which will need IP Services license to support it.

2. Configure your peering transit interface for IPv6. Usually this is provided by means of a /64 for strict transit usage. My example uses SVI:

 sw1(config)#int gi0/11
 sw1(config-if)#description "physical circuit interface"
 sw1(config-if)#switchport access vlan 1000
 sw1(config-if)#exit
 sw1(config)#int vlan1000
 sw1(config-if)#description "logical peering SVI interface"
 sw1(config-if)#ipv6 enable
 sw1(config-if)#ipv6 add 2001:db8:c001::2/64

3. After verifying L3 connectivity, let's get started on the BGP configuration. First lets configure our inb/outb filters. For the sake of this example, let's assume default in and two custom prefixes out. These "filters" will be prefix-lists, with route-maps configured for flexibility at the BGP config level.

  • Inbound is easy enough; allow default
 ipv6 prefix-list UNICORN-NETWORKS-ipv6.in seq 5 permit ::/0
  • Outbound is also simple, just specify YOUR prefixes, whether from your ISP or RIR
 ipv6 prefix-list UNICORN-NETWORKS-ipv6.out seq 5 permit 2001:db8:dddd::/56
 ipv6 prefix-list UNICORN-NETWORKS-ipv6.out seq 15 permit 2001:db8:eeee::/56
  • And route-maps matching our configured prefix-lists; route-map allows for flexibility and should always be used
 route-map UNICORN-NETWORKS-ipv6_in.map permit 100
  match ipv6 address prefix-list UNICORN-NETWORKS-ipv6.in

 route-map UNICORN-NETWORKS-ipv6_out.map permit 100
  match ipv6 address prefix-list UNICORN-NETWORKS-ipv6.out

4. Once we are ready with our filters, we can get going with the actual BGP process configuration. First, enter the BGP router configuration and configure your peer ISP neighbor, but at this point, it will be disabled until your IPv6 family configuration exists. Second, enter the 'address-family ipv6 unicast' context and specify your networks to advertise and your neighbor activate/route-map commands as you see below. This should complete your basic IPv6 BGP configuration and we can move on to some verification

 router bgp 65222
  neighbor 2001:db8:c001::1 remote-as 65111
  !
  address-family ipv6
   network 2001:db8:dddd::/56
   network 2001:db8:eeee::/56
   neighbor 2001:db8:c001::1 activate
   neighbor 2001:db8:c001::1 route-map UNICORN-NETWORKS-ipv6_in.map in
   neighbor 2001:db8:c001::1 route-map UNICORN-NETWORKS-ipv6_out.map out
  exit-address-family
  • If you haven't done so already, make sure that your prefixes exist in the global RIB ('show ipv6 route') in order for BGP to inject them into the BGP IPv6 RIB. The prefixes you specified in the BGP configuration will not be advertised if they don't exist in the global RIB. If they are not, you can create a placeholder route for now, with the 'ipv6 route' command (Example: ipv6 route 2001:db8:dddd::/56 Null0). Directing traffic towards Null0, essentially discards the traffic when it is processed by the routing engine. This is good if you plan to distribute your larger prefix into smaller /64 size subnets, because it will discard the traffic that doesn't match a more specific route but this is a whole different topic to go on about =). For now, it will allow the route to be propagated into the BGP IPv6 RIB since Null0 is always reachable.

5. You can quickly verify IPv6 BGP neighbor status with 'show bgp ipv6 unicast summary', which will list the neighbors and if your BGP state is 'Established', then you will not see a BGP state, but instead, a count of prefixes received from that specific neighbor:

 sw1#show bgp ipv6 unicast summary
 BGP router identifier 2.2.2.2, local AS number 65222
 BGP table version is 2
 1 network entries using 172 bytes of memory
 1 path entries using 88 bytes of memory
 1/1 BGP path/bestpath attribute entries using 136 bytes of memory
 0 BGP route-map cache entries using 0 bytes of memory
 0 BGP filter-list cache entries using 0 bytes of memory
 BGP using 420 total bytes of memory
 BGP activity 4/0 prefixes, 6/2 paths, scan interval 60 secs
 
 Neighbor	V	AS	MsgRcvd	MsgSent	TblVer	InQ	OutQ	Up/Down	State/PfxRcd
 2001:db8:c001::1
  		 4	65111	83	82	2	0	0	01:08:02	1
  • And you can verify received prefixes by checking the global and BGP IPv6 RIBs
 sw1#show bgp ipv6 unicast
 BGP table version is 2, local router ID is 2.2.2.2
 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
               r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
               x best-external, a additional-path, c RIB-compressed,
 Origin codes: i - IGP, e - EGP, ? - incomplete
 RPKI validation codes: V valid, I invalid, N Not found
 
 	Network		Next Hop	Metric	LocPrf	Weight	Path
  *> ::/0		2001:db8:c001::1     0     100       0  65111 i

 sw1#show ipv6 route
 IPv6 Routing Table - default - 11 entries
 Codes: C - Connected, L - Local, S - Static, U - Per-user Static route
        B - BGP, R - RIP, I1 - ISIS L1, I2 - ISIS L2
        IA - ISIS interarea, IS - ISIS summary, D - EIGRP, EX - EIGRP external
        ND - ND Default, NDp - ND Prefix, DCE - Destination, NDr - Redirect
        O - OSPF Intra, OI - OSPF Inter, OE1 - OSPF ext 1, OE2 - OSPF ext 2
        ON1 - OSPF NSSA ext 1, ON2 - OSPF NSSA ext 2, a - Application
 B    ::/0 [20/0]
 	 via FE80::6665:9DFF:FE34:4D31, Vlan1000
 S    2001:DB8:DDDD::/56 [1/0]
	 via Null0, directly connected
 S    2001:DB8:EEEE::/56 [1/0]
	 via Null0, directly connected

 (.. Other link-local routes ommitted ..)

You can see that the received route made it successfully into respective IPv6 RIBs, accompanied by the static routes created earlier for injection into BGP. The routes should propogate fairly quickly into the many looking glass servers available on the WWW today and can also be verified via traceroute (you can use a web tool such as http://ping.eu/traceroute if you do not have IPv6 client access).

After successfully deploying IPv6 at your edge network, there are several different options for moving IPv6 into your core infrastructure. You can go dual-stack from the edge to the server, which would be the most difficult. Another option would be to choose a IPv4/IPv6 segregation point in your network, to perform translations or act as an IPv6 proxy towards your IPv4 servers. If your a hosting or cloud service provider, the ladder seems to be the best option as it provides an easy migration path from IPv4 to IPv6 on the application side, if done right; you can support IPv6 to your load balancer, proxying traffic to your IPv4 servers, with the option to add your IPv6 servers to the LB pool once you are ready and migrate to them seamlessly.

Hope this helped as a primer and to give you a basic path for moving towards IPv6 at the network infrastructure level (or just to test it at the very least).

Feel free to ask any questions or drop a comment!