Repeating Number IP Addresses
Google started a bit of a trend when it released its own DNS service on IP address 8.8.8.8.
The thing about a DNS service, is that when you want someone to be able to use it, they need to know how to configure it. But you can’t use a nice memorable name, as the whole point of a DNS service is to translate names into IP addresses. So you have to configure your DNS service using the IP address alone, hence Google finding a way to secure ownership of the 8.8.8.8 address for use with DNS, landing them a nice, easy to remember address.
Now, more recently, the Quad9 DNS service has been launched, promising more privacy and performance, on, you guessed it, 9.9.9.9. And in the last month or so Cloudflare and APNIC have teamed up to bring you the 1.1.1.1 DNS service, again promising privacy and performance.
So this got me wondering – who might be next? Well if you’re after memorable IP addresses, then repeated numbers is definitely the way to go, so after a quick bit of typing into an IP address lookup tool, how about some of these?
- 2.2.2.2 – Orange Telecom
- 3.3.3.3 – Amazon
- 4.4.4.4 – Level 3 Communications
- 5.5.5.5 – E-Plus Mobilfunk GmbH & Co KG
- 6.6.6.6 – USAISC – looks like US Army
- 7.7.7.7 – Dept of Defense
And of course we know about 1, 8 and 9. I’m not interested really in 10, but going for other repeats:
- 11.11.11.11 – US DoD again
- 22.22.22.22 – And this one too …
- 33.33.33.33 – And this one …
- 44.44.44.44 – US Amateur Radio Digital Communications
- 55.55.55.55 – USAISC again
- 66.66.66.66 – Time Warner Cable Internet LLC
- 77.77.77.77 – Dadeh Gostar Asr Novin P.J.S. Co. (with an address in Iran)
- 88.88.88.88 – Telenor Business Solutions AS (Norway)
- 99.99.99.99 – AT&T
- 111.111.111.111 – KDDI (Japan)
- 222.222.222.222 – China Telecom
So the US military certainly has ownership of the largest number of repeated number addresses. But there are also a fair number of telcos and large Internet companies in there too (will we eventually see an Amazon DNS service on 3.3.3.3 I wonder?).
Of course if you were running a universal query answering service, then the best address would have to be 42.42.42.42, which appears to be owned by South Korea Telecom.
But I dread to think what running a single service on any of these specific public addresses would do to the global routing table.
Of course you need to beware of hidden meaning in all this … although taken to extremes it reminds me of the interesting number paradox.
When you see the number 111 stop and look around yourself. Take a note of where you are, what you are doing and who you are with! 111 is a wakeup call from the Universe, telling you to pay attention to what is happening around you.
That’s not a bad premise for a DNS service – as a reminder to pay attention to the real world.
Kevin
MIDI Arp
I wanted to do something with MIDI and Arduino. I’ve just picked up some cheap Arduino Nano Ethernet shields, based on the Microchip ENC28J60, so thought I’d combine the two. The ENC28J60 and a cheap Arduino Nano makes for a very compact and economical Ethernet ready microcontroller and I have a nice Roland MT-32 Synth module gathering dust that I wanted to try again.
My initial idea was to use MIDI to trigger sounds based on arp requests received by the Arduino, (hence the name MIDI Arp), but then decided that on my home network arp requests wouldn’t give a lot of variation, so I decided to see if I could trigger on the destination IP address of any packet received.
First I needed the MIDI interface. I followed the simple circuit and example provided on the Arduino website, but wanted it all self-contained inside a MIDI plug rather than on a breadboard, so I soldered up the 220 resistor inside a 5 pin MIDI DIN plug as follows (MIDI pins are number 1, 4, 2, 5, 3 for some reason):
- Arduino GND – Brown – MIDI Plug pin 2
- Arduino 5v – Red – 220 Ohm resistor – MIDI Plug pin 4
- Arduino TX (Pin 1) – Orange – MIDI Plug pin 5
This was then connected to the Arduino and the MIDI test programme showed that all works fine.
So, to the Ethernet side of things. The following is an excellent starting place for the ENC28J60 based nano shield:
After reading this, I decided to use the UIPEthernet library as my starting point as I liked the idea of a plug-in replacement to the standard Arduino Ethernet library. There was two major things to work out – first, how to set the device into some kind of promiscuous mode, assuming it supports it at all; second how to grab the destination IP address from any received packets.
From the ENC28J60 data sheet, the key register that controls the receiver filtering is the Ethernet Receive Filter Control Register – ERXFCON (see section 8 ‘Receive Filters’). There are a number of modes for filtering and the UIPEthernet library is set up to filter for the unicast address associated with the MAC address configured for the module, for broadcasts, and to use the pattern matching filter to spot arp packets. It turns out that to set the receiver into promiscuous mode, this register just has to be set to zero.
Now this is where things got lazy. I just dived into the UIPEthernet library sitting in my Arduino library folder and hacked about. I might tidy this up one day and do it properly.
The low-level driver code can be found in utility/Enc38j60Network.cpp. In the Enc28J60Network::init function, there is a line that sets up the ERXFCON register:
writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN);
This needs to simply be changed to clear the register:
writeReg(ERXFCON, 0);
Next, how to store the destination IP address. Again, simplicity ruled this one too.
The high-level interface to the library can be found in UIPEthernet.cpp and UIPEthernet.h. I added two public functions and two private variables to the UIPEthernetClass class in UIPEthernet.h:
public: IPAddress lastSrcIP(); IPAddress lastDestIP(); private: static uip_ipaddr_t uip_lastipsrc; static uip_ipaddr_t uip_lastipdest;
Then in the UIPEthernet.Cpp file, added the code to store the last source and destination IP addresses from received packets.
First, define a structure to dig into to the IP header (a bit of a layer violation, but I wasn’t after neat designs really). Add the following after the definition of ETH_HDR near the top of the file.
#define IPBUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
Then add two (static) global variables to the file:
uip_ipaddr_t UIPEthernetClass::uip_lastipsrc; uip_ipaddr_t UIPEthernetClass::uip_lastipdest;
Add two accessor methods to retrieve the last source and destination IP addresses (with appropriate conversion to the Arduino Ethernet friendly IPAddress format):
IPAddress UIPEthernetClass::lastSrcIP() { return ip_addr_uip(uip_lastipsrc); } IPAddress UIPEthernetClass::lastDestIP() { return ip_addr_uip(uip_lastipdest); }
Finally add the code to save the addresses to the UIPEthernetClass::tick() function, on reception of a packet.
Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) { uip_packet = in_packet; //required for upper_layer_checksum of in_packet! #ifdef UIPETHERNET_DEBUG Serial.print(F("readPacket type IP, uip_len: ")); Serial.println(uip_len); #endif uip_arp_ipin(); uip_input(); if (uip_len > 0) { uip_arp_out(); network_send(); } // Extra code added here uip_ipaddr_copy(uip_lastipsrc, IPBUF->srcipaddr); uip_ipaddr_copy(uip_lastipdest, IPBUF->destipaddr); // Extra code ends }
That should be all that is required to expose the destination IP address of any received packet via the UIPEthernet class (ok, breaking compatibility now with the standard Arduino Ethernet library).
The arduino sketch file now consists of the following:
/* MIDI based on http://www.arduino.cc/en/Tutorial/Midi UIPEthernet Examples used for rest NB: Requires hacked UIPEthernet Library! */ #include <SPI.h> #include <UIPEthernet.h> #include "IPAddress.h" int lastIP; int thisIP; // Initialise note array with whole tone scales in octaves 3 through to 6 // C3 = 36 // C4 = 48 // C5 = 60 // C6 = 72 // C7 = 84 #define NOTES 24 int notes[NOTES] = { // C3 D3 E3 F#3 G#3 A#3 36, 38, 40, 42, 44, 46, // C4 48, 50, 52, 54, 56, 58, // C5 60, 62, 64, 66, 68, 70, // C6 72, 74, 76, 78, 80, 82 }; void setup() { // Set MIDI baud rate: Serial.begin(31250); // Initialise the uIP and UIPEtherent stacks uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; IPAddress myIP(192,168,0,6); lastIP = 0; thisIP = 0; Ethernet.begin(mac,myIP); // Initialise patch using program change // 32 = Synth 1, Fantasy midiCmd (0xC0, 32); } void loop() { Ethernet.maintain(); IPAddress sip = Ethernet.lastSrcIP(); IPAddress dip = Ethernet.lastDestIP(); thisIP = 256*dip[2] + dip[3]; if (thisIP != lastIP) { lastIP = thisIP; int note = (thisIP & 0xff) % NOTES; // Scale to number of notes int vel = ((thisIP & 0xff00) >> 8)/4; // Scale to val between 0 and 64 //Note on channel 1 (0x90), some note value (note), middle velocity (0x45): noteOn(0x90, notes[note], 16+vel); } } // plays a MIDI note. Doesn't check to see that // cmd is greater than 127, or that data values are less than 127: void noteOn(int cmd, int pitch, int velocity) { Serial.write(cmd); Serial.write(pitch); Serial.write(velocity); } void midiCmd(int cmd, int val) { Serial.write(cmd); Serial.write(val); }
The final byte of the IP address determines which note from the array of notes to play (modulo the number of notes) and the third byte determines the volume to be used, scaled and with a minimum specified.
There is a control message to set the voice on the MT-32 to Synth1-Fantasy as this sounds suitably ambient. There are no note-off messages, so notes are allowed to keep ringing. As the note array defines four octaves of whole tone scales, the running-on notes create quite an interesting effect.
There seems to be a regular drone set up, which I think is due to the IP address of my PC and router. These two addresses provide a sort of default back-drop of sound to anything else going on.
In order to get anything useful though, it would be no good just using a port on the router, as even the dumbest, cheap modern router will tend to do some MAC level filtering on ports. I had a laptop and the Arduino plugged into an old Netgear En104 4-port Ethernet hub, which has no intelligence (as far as I know) built in – so the Arduino could see everything coming out of the laptop.
The results were quite pleasing. Google has a nice enhanced drone to it. You can really hear the clutter of a site that is pulling in ads from all over the Internet – such as Amazon or YouTube or a news site.
Edited to add: Here is a short video below showing them being opened. It’s a bit crude but you get the general idea.
Maybe next, I’ll see if I can do the same with a Wi-Fi link for the Arduino instead of wired Ethernet. It might also be worth trying different scales and alternative mappings of notes to addresses.
Kevin
RPi Ethernet and Wifi at the same time
This should have been a lot easier than it ended up being! I wanted to turn one RPi into a router between its Ethernet and Wifi networks, so that a single wifi dongle could be shared across a few Ethernet devices (via a simple dumb Ethernet hub I had lying around).
Well there are lots of posts around the Internet showing how to configure the Pi as an Access Point or an Ethernet Bridge, but in all discussions of the /etc/network/interfaces file I’ve found, no-one has really (that I’ve found so far) mentioned quite how the wpa_supplicant, ifconfig and ifplugd systems all interact and fit together.
Whilst a number of people have speculated that there might be power supply issues that will knock out your Wifi if you plug in an Ethernet cable, I didn’t see any evidence of that. What I was actually seeing is ifplugd detecting the plugging in of the cable and then running its action scripts in /etc/ifplugd/action.d. On my version of Raspbian, one of these scripts is a symlink over to /etc/wpa_supplicant/action_wpa.sh which basically disconnects any wpa-roam managed interfaces if the Ethernet is plugged in.
This is the designed-in behaviour, as the basic idea is that if you are using Ethernet and Wifi, then typically it will be to the same network (and ultimately connected to the Internet) so it will only need Wifi when the Ethernet is not connected. If you have a wired connection, it will disable the wireless connection to use the wired for preference, which is the desired behaviour in the vast majority of cases.
There are a number of “fixes” around the Internet, from killing ifplugd to removing or adding auto or hotplug related options in /etc/network/interfaces. I’m sure there must be some magic combination of options that means that the hotplugging of cables and dongles can still work, but will not automatically turn the wifi on and off – but I haven’t found it yet.
Instead, I went for the very simple, but almost definitely “quick hack” version of including an “exit 0” command near the top of /etc/wpa_supplicant/action_wpa.sh before it actually did anything. This way, I get to keep the automatic configuration on plugging cables and dongles in, but the arrival of a new interface does not automatically shutdown the wpa-roam managed ones.
This seems to work really well for keeping Wifi connections open when plugging in an Ethernet cable. When plugging in a Wifi dongle, that also seems to work, in that both Ethernet and Wifi end up active – although I did get a break in continuity over the Ethernet when this happened – but it reconnected again fine.
Of course, this may well completely shaft true wifi roaming across networks – I don’t know – I don’t take this RPi out and about to test it and I haven’t read enough how the wpa-roam system is meant to work to see.
I expect there is a more elegant way to achieve this, but the Internet wasn’t providing it; the Debian networking configuration manual seemed to be suggesting that I should probably use the GUI and that everything else is legacy; and I’d had enough of reading man pages. If you know of a good reference for how these scripts all interact and how this can be achieved in a nicer way, I’d very much like to hear from you!
But, this will do for now for my relatively static setup of single Wifi network, routed across to the Ethernet network.
Kevin.
Find my (R)Pi
I like tinkering with my Raspberry Pi, but I also tend to have them configured for remote SSH to save dragging out a keyboard and screen. I also use the small Edimax WiFi USB dongles, but I also just like to let the pi find its own address on the network using DHCP … so I often need to either hook up to my routers admin/status page to see what nodes it has found or just attempt to connect to a few nodes in the range I know will be used for the pi.
Eventually I got fed up with doing this, so instead I wrote a very simple perl script to use Net::Ping to scan a small range of addresses and report on which ones are responding, and then see if port 22 (SSH) or 80 (web) are open. Then I know where my pi is.
Net::Ping can use the tcp for ping, which has the advantage that you don’t need privileges for the script to use icmp. The disadvantage is that most things won’t respond to the tcp echo port. Consequently, I use Net::Ping in two modes – first with icmp to see if the host is alive, then with tcp to probe the ports I’m interested in. This does require it to be run with administrator privileges, but that is fine for me.
I don’t scan a whole range, that would take too long for this very simplistic case, so I just scan 20 or so addresses that I am interested in.
There are a wealth of network scanning and management applications out there, but this has the advantage of being very simple. Just what I needed. Below is the code. Nothing exciting – about as simple as it gets, but it works.
To run from Windows, I use a simple batch file to call the perl interpreter with the script, then pause afterwards (to give me a chance to read the output). This can then be used by right-click -> run as administrator.
Kevin
#!/usr/bin/perl -w use Net::Ping; my $subnet="192.168.0."; my @ports = (22, 80); my $timeout = 1; my $p_icmp = Net::Ping->new ("icmp", $timeout) or die "Can't start icmp ping"; my $p_tcp = Net::Ping->new ("tcp", $timeout) or die "Can't start tcp ping"; for ($i = 50; $i<70; $i++) { my $host = $subnet.$i; print "$host: "; if ($p_icmp->ping ($host)) { print "ok "; foreach my $port (@ports) { $p_tcp->port_number($port); if ($p_tcp->ping ($host)) { print "$port "; } } print "\n"; } else { print "nok\n"; } }