- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
That tuple situation reminds me of Javascript code I see online where authors seemingly adhere to the rule of "make it as dissimilar to other C- style languages as possible".
Admin
This whole "UDP to Google dial" can't be replaced by calls you mentioned. The whole point of that construct is that OS fills sender address with proper outgoing address with regard to routing table. If you have many cards or many aliases, that construct fills the one actually used to reach the outside world.
To get that by hand, you have to inspect the routing table and then iterate over all the interface aliases to find one, for which the default/desired route's gateway matcher network. Doable but tedious and error-prone.
BTW, it is a go-to snippet not only in Python, but also in Go.
Addendum 2021-08-12 07:42: EDIT: I'm not commenting the rest of that miserable piece of code - just the underlying mechanism.
Admin
Pawel Kraszewski - for the win. (not meaning windows :) )
Admin
The WTFery begins right here, with the assumption that there is one IP address. (It's also wrong in that the Linux code requires an interface name, and therefore is asking for "the" address on the interface rather than on the computer.) It's easy to imagine a slightly ... obscure ... configuration where there are two addresses on the interface (10.0.0.42/16 and 192.168.1.42/24, say) and the default route (or, perhaps, the relevant route) passes via the non-first address, in which case the Windows method will work, but (see below) the Linux one will not.
And I'd like to see the justification for the assumption that the source address that's suitable for reaching Google's DNS server is also suitable for reaching whatever services the vendor uses. And for using port 80 in a UDP connect() call where the destination address is a DNS server. And for assuming that the source address used for reaching whatever address we want is actually on the requested ifname.
And of course the 35093 in ioctl(s,35093,...) is SIOCGIFADDR (get interface address). It takes the given interface name and returns "the" address, presumably the main or "first" one. See above for why that's wrong, given that we presumably want the source address used for communicating with the vendor's distant server. Maybe.
Overall, this code is a mystery, and wrong in various ways, and it would be easier to decode if we knew what the return value is being used for. (Noteworthy: in modern - i.e. any time after the mid 90s, maybe earlier - networks, the IPv4 address(es) on machines inside networks are rarely very unique, being mostly variations on 10., 172.16-31. or 192.168...)
(1) FreeBSD does this, but Linux (Ubuntu 18.04) does not.
Addendum 2021-08-12 07:55: Ignore the footnote. It was relevant until I reread the code, and realised that it asks about a specific interface, in theory.
Admin
Only if you want the proper outgoing address for reaching Google's DNS server. If the vendor's software wants to know the IP address for reaching the vendor's servers, it's better to use one of their addresses, in case the client's network has funky routing tables.
Admin
TRWTF is trying to get "the" IP address. This is anything but straightforward: Nowadays, computers have multiple network interfaces which could be in use at the same time (think LAN, WLAN plus some VPN tunnels); then we have two IP protocol versions that might be used in parallel on those interfaces, both of which are able to assign multiple IP addresses per interface (with IPv6 very often making use of this feature by default).
So "let's pretend we'd connect to a well known public server and see which source IP would be used" is a valid approach and a lot better than "try to guess it" or "take the first".
(Note that all this would not mean that the chosen address would show up as the source IP at the chosen server if we'd really make the connection.)
Admin
And is UDP to port 80 even open on Google's end for DNS, or was it chosen because it would be blocked?
Admin
Multiple IPs on the same interface in Windows is extremely common for webservers. It was even more common before SNI let us overload multiple https sites on the same port. Generally, though, the multiple IPs are all on the same subnet ... multiple subnets is, indeed, obscure. I've used it in my home lab though.
BTW, what the hell is up with login to this site? I got a complaint that login through Google is disallowed because thedailywtf doesn't obey OAUTH2 properly.
Admin
I think they may be using the IP for licensing. They don't want you to hide multiple computers behind a single NAT/PAT address, so they check it on the client. They don't care which IP may be used for a connection to their servers, it just has to pick the one that matches the license. They accept private IP's with the idea that you won't use the same IP on multiple machines. Doesn't matter if a different client licenses those same IP's.
Admin
This code doesn't seem to know about macOS (sys.platform == 'darwin') or other more obscure platforms and falls into the Windows case for those.
This code was also likely written for Python 2. If you pass a str for ifname in Python 3, it fails with:
So either the ifname would be passed as a bytes object already (unlikely, IMO), or it should be encoded into a bytes object to work correctly in Python 3.
Admin
That's sounds like complicating the process for a very weak defense. It's trivial to set up virtual machines that NAT to the physical network... and there's nothing stopping every VM from having the same IP in this configuration. All of the container technologies I'm aware of make it even easier.
Admin
Minor thing: It is
elif
, notelsif
as written in the article.Admin
"One of the advantages of interpreted languages, like Python, is that when your vendor ships a tool that uses Python… you can see how the Python bits actually work." - it used to be standard to get the source code for applications so that if the vendor went out of business you could at least maintain what you had.
Admin
Interestingly, and although you are largely correct (contracts used to include a provision for storing the source code with a trusted legal service), this doesn't necessarily apply even within the same organisation.
I've worked with a major credit card provider that had massive amounts of Cobol code sitting on the mainframe servers. Not in Cobol, you understand: just in the compiled version. Somewhere inside that gibberish it assumed that there would only ever be exactly four LU6 connections to the outside world. (Well, the FEPs, but whatever.)
We added two more FEPs, and something not very close to hilarity ensued. The loons had failed to save the original Cobol (or probably the "real time" equivalent, which was ATM or something or other).
Nobody volunteered to fix the assembly language version, so we had a lot of fun implementing our own proxy server ...
Admin
Jamie, I didn't say it was a good way, but it is done.
Admin
TRWTF is assuming the number of IP addresses requires fewer than 2 digits to express in decimal.
The Windows code is a solid fallback! They didn't need if statements at all.
You also have to figure out which routing table is in effect, and if there are any nondeterministic or stateful firewall rules that act as routing table inputs.
It's useful for tracking usage inside corporate clients. The licensor can provide the licensee with a list of dates, times, and local IP addresses, so they can figure out who's using up all their licenses. It's useful if the license manager doesn't have some better identifier like a user name, or that name is "Steve" and you hired hundreds of Steves, or everyone runs the software as "ProductionAccountUsername".
Admin
There is confusion about what the function is doing. There's no DNS involved. Its trying to get an address for an interface, such as 'eth0'.
Probably as some have noted that its for license verification. I recall some products which did that, but they enumerated all available addresses. When upgrading servers I would sometimes need to add a virtual address eth0:1 but keep it 'down'.
Admin
It still is pretty common with niche enterprise systems... several of our clients have an escrow arrangement, where if we go under, they receive a copy of our code. Probably not very useful in practice unless they also hire themselves a team of recently-unemployed system experts to maintain it, but it ticks some legal boxes for them.
Admin
Python isn't interpreted, it's compiled into bytecode that runs in a Forth-like stack machine.
It's actually less of an interpreted language than Java.
Admin
There is only one way to get an IP address: ask the user. The idea of doing a lookup on the hostname (as it does in Java) is utterly useless and the article should be ashamed for suggesting it.
If this is attempting to ID a host for licensing then it's even more stupid because addresses change.
There is only one use for an IP address found in code: you have a mandatory field to complete and don't care what goes in it!
Admin
Way back when I didn't know better, I wrote a LOT of code that would run "netstat" or similar in a shell and parse the output to get net or interface info. It only took like two days every time I tried it on a different machine, to adapt to all the various unexpected gibberish that can come out of netstat. Still have a mild headache from all that.