Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Please do not put IP addresses into DNS MX records (hboeck.de)
228 points by hannob on Feb 21, 2021 | hide | past | favorite | 176 comments


I agree with the article, but I would go even further. This whole thing is stupid. You physically can’t put an IP address into an MX DNS record. What the syntax (perhaps misleadingly) allows is to put a domain name there with labels consisting of only digits. That is, the “IP adress” 1.2.3.4 you wrote in your MX record is actually the domain name "1.2.3.4.yourdomain.com" with “1”, “2”, “3”, “4”, “yourdomain”, and “com” as the individual domain labels. There is no way to actually store an IP address in an MX DNS record. It just so happens that the usual syntax for IPv4 addresses turns out to be valid syntax for an (unrelated) domain name as well.

And, of course, if you try to write an IPv6 address, it will naturally fail, since IPv6 addresses uses colon “:” characters, which are not allowed in domain names.

Therefore, it would be beyond silly for programs to actually use these invalid domain names in MX records. MX records which point to domain names which cannot be resolved are simply broken.


Out of curiosity though: why is it like this? Wouldn't it make a lot more sense to set an IP address instead of a hostname? Now the admin needs to keep track of an additional DNS entry (for the mail server) and the client has to make one additional request.


It's a good question. It did not have to be designed this way, and indeed there have existed for some decades now DNS content server softwares that hide this indirection from administrators as a convenience, and synthesize the intermediate domain names if necessary. For example, the back-end database for tinydns has "@" records in its source data files, and an administrator can (optionally) just enter:

    @example.net:192.0.2.0::10
tinydns synthesizes "mx.example.net." for the intermediate domain name.

* http://jdebp.uk./Softwares/djbwares/guide/commands/tinydns-d...

That said, the SMTP Relay server needs to know that "mx.example.net." is one of its names, if it is a fallback server.

One can envision a world where records in the DNS database map a (domain,service,transport) tuple directly to a set of (address,port,preference,weight) tuples, where that is what administrators consistently deal with for everything, where that is how the on-the-wire protocol actually works, and where SMTP Relay loop prevention works by comparing IP addresses; but SMTP doesn't work like that, the DNS did not start out like that, the DNS has gone through at least two iterations to even get to where it is now with SRV and MX records, and the DNS has grown through fitting new mechanisms against existing ones.

One point about "mx.example.net.": If the intermediate domain names are in-bailiwick like that, and the MX response contains "glue", then it is not actually "one additional request".


> That said, the SMTP Relay server needs to know that "mx.example.net." is one of its names, if it is a fallback server.

It also would need to know its name in order to have SMTP over TLS to work (as required by DANE).


> Out of curiosity though: why is it like this?

In order to have a pointer to what you actually want to have.

MX points to a hostname. This hostname can have many records including A, AAA, TXT, etc which are used by MTAs such as postfix and sendmail for delivery and verification. Also you'd have to make changes only in the hostname records which would affect all other records in the zone that point to it. Easier to maintain.


Only A and AAAA records take an IP. Everything else is a hostname. This simplifies administration, as there's only one hostname->IP config point, so you have the flexibility to resolve the rest dynamically.


An MX record is a mail authority delegation.

The History Department at a major university could delegate mail to be handled by the schools IT department and need not be involved in the movement of a mail server from one IP to another.

This decision was made in a time when running mail involved lots of external coordination and was best delegated to a single central group, whereas a simple web server could be spun up by a technical person within the History dept.


MX records are used to point to mail servers by name. A/CNAME records handle redirection and pointing a name to IPs.

Having different DNS types helps simplify administration far more than the overhead of another entry.


It’s been the way since way back in the 80s.

Domain name is often the best way to go. Esp if different organisations are involved (like a mail hostel.)


What if I write 4.3.2.1.in-addr.arpa. instead?


That's a name, not an IP address. And what you would expect to find at that name is not an A record for that IP address (which would be redundant) but a PTR record providing its canonical name.


At some point someone’s going to get the .0 to .255 TLD somehow and cause a security fuffle.


According to RFC 1123:

However, a valid host name can never have the dotted-decimal form #.#.#.#, since at least the highest-level component label will be alphabetic

https://tools.ietf.org/html/rfc1123#page-13


As luck would have it, that’s probably not going to affect most people, because people who write an “IP address” in an MX record probably also didn’t put the terminating period at the end. Therefore, the MX record to “1.2.3.4” resolves to the local name “1.2.3.4.example.com” and not a domain in the hypothetical “.4” TLD.


Some software / sites put one there for you. Which is annoying when you don't want it.


Now I wonder how many of these might have the ability for users to create subdomains ... shades of being able to make "webmaster@" addresses for email sites and get an SSL cert or whatever.


Finally, 359.33.9.234 can be real.


> 359.33.9.234

I searched to see where it's from (CSI: Miami) and found a screenshot of it in a gallery with even more egregious examples, like 67.259.2942.1003 and 8394.83.384.38482:

https://www.root.cz/galerie/pocitacove-nesmysly-ve-filmech/#...


It's a simple way to avoid numbers on-screen from coinciding with any real IP addresses. It's the equivalent to phone numbers always starting with 555.


I'm not sure if this is still the case, but 555-1212 is the number for directory assistance.


NANP [1] has reserved other line numbers for other uses, including specifically entertainment

[1] https://nationalnanpa.com/number_resource_info/555_numbers.h...


In an alternate timeline, using four 16-bit numbers instead of octets could very well have been a solution to the IPv4 shortage. :)


Or in the future, CHAOS-2 could use one 1024 bit decimal number, making IPV6 obsolete, and disrupting the page layout of HN threads!

https://en.wikipedia.org/wiki/Chaosnet

All hail the second coming of Chaosnet, the return of the Tzeentch Control Protocol!

https://lovecraft.fandom.com/wiki/Chaos_God

>Major Chaos Gods

>Tzeentch: The Architect of Fate, who uses powerful sorceries to alter the future. He was once the greatest of the Chaos Gods and is potentially the most powerful. He's the God of Change, who endlessly plots and schemes, in a cosmic-wide game of subterfuge and manipulation. He became fully sentient in the 2nd millenium, due to mankind during Earth's medieval period. Tzeentch listens to the hopes of all mortals, feeding on their need and desire for change.


“1.2.3.4.in-addr.arpa.” would work, no?


> You physically can’t put an IP address into an MX DNS record

Per TFA,

> some mail servers do configure an IP address. Many mail servers are lenient when it comes to this misconfiguration and will deliver mails nevertheless

I.E. people can and do put IP addresses into these things. And any actual example is a complete rebuttal of claims of impossibility.

Standards don't have any cosmic significance. If people use a thing in a manner, then it's also that thing.


No, they do not. They put a domain name whose human-readable form just happens to resemble the human-readable form of an IP address into the record. An actual machine-readable IP address, and the actual machine-readable domain names that go into MX resource records, are quite different things, and one simply cannot put one into the other. This has been pointed out several times in this discussion.

It has been further pointed out that even if dealing with human-readable forms in (say) BIND's "zone" format files, the human-readable form of an IP address doesn't actually get translated into a 4-label domain name, because it isn't a fully-qualified human-readble domain name. Human-readable IP addresses don't end in dots, and if one has typed in a human-readable IP address into a "zone" format file, one actually has not made the relevant misconfiguration; and conversely if one has made the misconfiguration (in a way that will actually work with dnscache et al.) what one has typed is not actually a vanilla human-readable IP address.

Ironically, neither the headlined article nor many in this discussion have noted that the SMTP standard's algorithm for loop prevention breaks when one does this in MX resource records for the same reason that it breaks when one uses alias domain names via CNAME records rather than the canonical domain names. SMTP Relay servers do not match the domain names in the data of MX resource records against (their own) IP addresses because ... well ... those domain names are not IP addresses.


"Standards don't have any cosmic significance." - true but then I suspect you would get a right shitty on if your preferred IP stack didn't generally behave in the same way as mine and you lost comms with the world.

This discusses some consequences of avoiding standards: https://tools.ietf.org/id/draft-thomson-postel-was-wrong-03....

Of course your DNS server can return whatever you fancy in response to a request. If you want to return an MX record that looks like an IP address then go ahead. I think the old restriction on a hostname being greater than two chars and no leading int has gone away. If a MTA is happy with the result then fine.

However, anti-spam systems will frown on things like that and will probably tut a bit. ... and drop your mail on the floor. You can do what you like - you could call these records "Liberty MX" but I will still drop your mail because I can't be arsed to analyse your intent. You don't follow email standards - DROP!


I think the point here is that the "lenient" behaviour actually is a lot more complex than one would expect - a compliant mail server would need some special logic to detect hostnames that kinda look like IP addresses and handle them in a special way - without this behaviour being in any way standardized.

E.g., the lenient server would have to treat the value "10.0.0.254" like an IP address but "10.0.0.256" like a hostname that requires DNS resolution.


This is a solved problem and not very complicated. For starters the last DNS label of a hostname cannot be all numbers: https://tools.ietf.org/html/rfc1123#page-13


But name stored in MX doesn't have to be FQDN. I can set up A record with real server IP at 1.2.3.4.example.com, then set 1.2.3.4 in MX for example.com, and it would be perfectly standard compliant record, while it probably would be misinterpreted by servers trying to be "lenient".


> But name stored in MX doesn't have to be FQDN.

On the contrary, an MX record can only contain a FQDN. If you type “foo” as your target in an MX record in your domain “yourdomain.example”, what actually gets stored in the MX record is “foo.yourdomain.example.”; a perfectly normal FQDN.


That doesn't sound right. A "tcpdump -n -s0 -x -X port 53" shows that the server simply returns "outlook-com.olc.protection", not a FQDN, for "dig mx outlook.com".


MX records are one of the few records that can contain name compression. I think you'll find you're looking at the labels for "outlook-com.olc.protection" followed by a pointer to "outlook.com." earlier in the message.

EDIT: Yep, wireshark shows the byte sequence c00c following "protection". c00c is a compression pointer to "outlook.com." in the question section of the message.


I cannot reproduce this behavior; I see the complete FQDN in the reply when I run the commands you specify.

I do, however, note that, in the -X part of the tcpdump output, the periods between labels are not really ASCII period characters, but simply displayed that way by tcpdump; these are in fact byte counts for the label lengths, which, since all the individual labels are below 32 characters in length, makes these bytes ASCII non-printing control characters, which tcpdump then displays as periods.

In another comment, eknshow writes¹ that DNS labels can either be specified inline with a byte count (as described above), or can be a pointer to another set of bytes. Could this be what you are seeing? That is, could the domain part be present, but specified as pointers and therefore not be obvious in the tcpdump output? One would have to carefully examine the raw bytes to be sure.

1. https://news.ycombinator.com/item?id=26217913


Thanks for the correction. Curious if these misconfigured MXs store 1.2.3.4. or 1.2.3.4.example.com.


Fair point. I just tested using tcpdump and the IP address in the response doesn't in fact end with a dot.


Sort of related, i've always appreciated Postfix error 221 "I can break rules, too. Goodbye." Nobody would normally see this curt attitude as it is hidden in the protocol, but I find it cute.

  $ nc 127.0.0.1 25
  220 localhost ESMTP Postfix (Ubuntu)
  GET
  221 2.7.0 Error: I can break rules, too. Goodbye.
Where:

  221 = 
   - 2XX = "(Positive Completion Reply): The requested action has been successfully completed."
   - 221 specifically, "Service closing transmission channel"

  2.7.0 = (class.subject.detail)
   - 2.X = "Success: Report of a positive delivery action."
   - X.7 = "Security or Policy Status"


Oh, DNS is full of these kinds of “not in a RFC but needed to resolve names” corner cases. I will show just one:

(While .foo is a real top level domain, Google doesn’t let the public register names in it. It would be nice if there was a “.example” TLD; “.invalid” looks wrong and using “example.(com|org|net)” is awkward when using multiple domains in an example. 10.X.X.X should not be resolved at the internet-wide DNS level in the real world, but these are examples, not real-world cases)

We get this packet when asking the domain1.foo nameserver for blog.domain1.foo

  blog.domain1.foo CNAME blog.domain2.foo
  blog.domain2.foo A 10.1.2.3
Should we use this A record? BIND, about 20 years ago, did use this A record. DJB rightfully screamed bloody murder (since BIND allowed domain1.foo to alter the cache for domain2.foo), and would not accept the IP. MaraDNS (Deadwood, these days), on the other hand, accepts the IP, but stores it in the domain1.foo record (so domain1.foo does not affect cache entries for domain2.foo).

Now, the correct thing to do is to not accept the domain2.foo record at all unless it comes from a server in domain2.foo’s bailiwick, since that is how modern versions of BIND do it. Otherwise, there are a small number of poorly configured corner cases (where domain1.foo has an outdated IP for domain2.foo) which will resolve incorrectly.

Now, back to the article, I believe DJB had a way of handling this: If it saw “domain2.foo MX 10.2.3.4”, it would then, if asked for the IP for the domain “10.2.3.4”, return the A record (IP) 10.2.3.4 (or was it Qmail which did the expected thing if it saw a dotted decimal domain name? Or both? There are enough old school DJB advocates here that someone should be able to clarify)

I know this much: DJB made some noise two decades ago that this is a real-world misconfiguration which should be accounted for and handled the expected way, calling them dotted decimal IPs.


> It would be nice if there was a “.example” TLD;

I don't understand what you want here. RFC 2606 reserves .example for the purpose of examples. I use it all the time for this purpose.

If you want to really register names under that TLD now it isn't an example any more and ceases to serve its purpose.


> While .foo is a real top level domain, Google doesn’t let the public register names in it.

For the record, example.com, example.net and example.org are reserved domains, that cannot be used. So you can always use those as safe examples. https://en.wikipedia.org/wiki/Example.com https://tools.ietf.org/html/rfc2606


It would have been nice if "cannot be used" meant that no one would be allowed to register it. From what I can see, example.org very much resolves and accepts HTTP connections. It even has an MX record...


> Should we use this CNAME record?

I think you mean “Should we use this A record?”?

> calling them dotted decimal IPs.

Thankfully, with IPv6 we don’t have to worry about it, since the syntax for IPv6 addresses are invalid as domain names.


Thank you for pointing out the typo; I have corrected the grandparent.


It was dnscache.

* http://jdebp.uk./Softwares/djbwares/guide/commands/dnscache....

* http://cr.yp.to/djbdns/dnscache.html

And it wasn't to do with bailiwick at all. It was to do with the fact that many softwares allowed users to enter either IP addresses or domain names; but either left recognizing IP addresses up to the DNS client libraries, some of which would in turn fail to do so and just treat them as domain names, or recognized IP addresses in a form that users would forget to use, such as having them enclosed in square brackets. M. Berstein's own DNS client library, and several others, do the same thing that dnscache did, in the client library itself, implementing this same defence at multiple layers of the system.

* https://cr.yp.to/djbdns/dns.html

A related scenario: Some Unix/Linux softwares allow one to specify users by either ID or name, but fail to take advantage of the fact that the colon is prohibited in account names, and so can be used as a syntax for unequivocally distinguishing between the twain. As a result, strings like "0" can potentially be mapped to something other than the superuser if someone goes and creates a user account with the name "0" (whereas ":0", as in the syntax for some tools, is unequivocally user ID zero and "0" generates an error unless there is actually an account by that name). This in turn leads to people arbitrarily banning account names with digits, and security holes resulting when the action upon encountering attempts to use such a name is to just ignore them. Recall the "User=0pointer" kerfuffle in systemd.


> Oh, DNS is full of these kinds of “not in a RFC but needed to resolve names” corner cases.

What? It's in RFC 1035, and that's noted in the article. There is lots of corner cases in the DNS. This is not one.


I would be interested to know why the RFC 1035 forbids using IP addresses in MX records. What was the original concern with doing this?


Looks like this goes back to the days when Internet with TCP/IP was not yet the only option and when there was also other networks available (Chaosnet). [1]

For the A records you can different classes of addresses. Nowadays we are using the "IN", but the spec also supports others like "CH" (Chaos) and "HS" (Hesiod).[2]

MX record points to mail.example.org (A-record). mail.example.org could then point to two different addresses in the different networks, using the different classes. Depending on what network the client is connected to, it can request specify the class in the query and get address on the correct network.

I guess they could have baked this in to the MX records as well, but that would have made it more complicated.

Disclaimer: Just googled this up.

[1] https://serverfault.com/questions/663112/why-cant-mx-records... [2] https://serverfault.com/questions/220775/what-does-the-in-me...


I guess nowadays that should still be useful to give both an IPv4 and IPv6 address for the mail server?


Yep, just have A and AAAA records for the hostname the MX points to


Why? You can just make mail.example.com resolve to two IPs: an IPv4 and IPv6 address. Nothing wrong with that.


Isn't that what Natsu said?


No. If you read the top-level comment, it sounds like the response directly indicates that these days it would be useful to use the defunct multiple classes (IN vs CH) functionality to instead reference different IP types (v4 or v6) in today's Internet, hence "nowadays". That isn't needed because we can already mix v4 and v6 records within the IN class itself through A/AAAA records.

If I misunderstood the comment, then my bad.


I see, I haven't had to dig too deep into DNS so it wasn't obvious to me that those were separated like that. I guess, then, that it's only useful to allow us to someday upgrade to some post-TCP/IP world if there's ever a reason for that.


DNS standards tend to favor using aliases rather than IP's. My observation is that the overall goal is to have the IP listed as few times as possible. Otherwise there'd be no need for CNAME's in general, and everything would be an A record or an IP. But, MX records are supposed to refer to an A record not an IP.

The author is correct- if somebody is doing this, they're simply doing it wrong. Standards exist so that we can say "This configuration is wrong" instead of "Lets complicate software to allow people to use any configuration they want."


> But, MX records are supposed to refer to a CNAME not an IP.

To be clear, MX records are supposed to point to an A record. Pointing to a CNAME record is not legal.


I can see the value in pointing at a name so TLS can validate correctly, but I don't see any value in limiting it to an A record.


Pointing to a CNAME isn't legal, but it should be. This particular limitation never made any sense to me and it should be lifted.


It might not be legal, but works quite well for me.

Having a dynamic IPv4 address with multiple domains on it, updating every record would take more time.

Admittedly, I could also have a copy of the IP per domain, but the CNAME was easier to setup.


That would require updating too much software in the field.

Meanwhile you can use ALIAS record and get the same result, without others noticing.


There is no such thing as an ALIAS record. That’s something your DNS provider made up and shows to you in the interface, but behind the scenes they are providing the same old AAAA and A records as always, along with some sort of auto-updating feature which they will run to detect changes in the address of the name in the “ALIAS record”. How often this will update is anyone’s guess as it’s up to the DNS provider.

See: https://en.wikipedia.org/wiki/CNAME_record#ANAME_record


Sorry to be pedantic, but there is no such thing as an ALIAS record. It's just the DNS server doing the indirection for you.


What if it's an AAAA record?


RFC 5321 is ambivalent of A vs. AAAA. When discussing the matter, 5321 says "A or AAAA RR". It later says about IPv6 that "The appropriate actions to be taken either will depend on local circumstances." When I re-wrote Gmail's DNS libraries about 6 years ago, I wrote it to start with AAAA and fall back to A. So if you have an MX and AAAA records for those names, you should notice all your inbound from Google comes via IPv6.


I've noticed that!

I believe Postfix also delivers to IPv6 if possible.


In my travels there's a significant portion of the internet which is not IPv6 capable; for example the World Community Grid failed for me when trying to use pure IPv6, and they send emails about things. I'd currently not risk using an IPv6 record for my MX, I suspect a high failure rate delivering email from every service on the planet will follow.


> set qu=mx > gmail.com. Server: 10.1.1.1 Address: 10.1.1.1#53

Non-authoritative answer: gmail.com mail exchanger = 20 alt2.gmail-smtp-in.l.google.com. gmail.com mail exchanger = 5 gmail-smtp-in.l.google.com. gmail.com mail exchanger = 40 alt4.gmail-smtp-in.l.google.com. gmail.com mail exchanger = 10 alt1.gmail-smtp-in.l.google.com. gmail.com mail exchanger = 30 alt3.gmail-smtp-in.l.google.com.

Authoritative answers can be found from: > set qu=aaaa > gmail-smtp-in.l.google.com. Server: 10.1.1.1 Address: 10.1.1.1#53

Non-authoritative answer: gmail-smtp-in.l.google.com has AAAA address 2607:f8b0:4001:c05::1a


Sure, but it has A records too.


I wake up and see the HackerNews downvote train has hit myself and you, when what you said is 100% correct; gmail-smtp-in.l.google.com is both IPv4 and IPv6.

The network I'm on right now (VPN to work) cannot service IPv6 and I cannot connect to the IPv6 IP for that MX host, but I can easily connect to the IPv4 endpoint.


I fixed it, that was a brain fart.


If it’s an IP address, you’re restricting it to IPv4 or IPv6. If it’s a name, then it can work on both IPv4 and IPv6.

You want pretty much everything but A and AAAA records to use domain names for pointing, so that they’re not tied to a particular version of IP. Keep the IP resolution to the last step only, and let everything else use domain names.


The RFC doesn’t “forbid” using IP addresses in MX records – it’s physically impossible to have them. The fact that the IPv4 address syntax is also parseable as a domain name is unrelated; what is physically stored inside the MX record is a textual domain name.


So you can have multiple address for the same MX, eg IN A 10.77.0.1 and IN AAAA fd77::1.


The RFC is pretty readable, but the tldr is that DNS is more strongly typed than that. It's not just a string-lookup service. There's a wire format for names, which some records carry; there are wire formats for v4 and v6 addresses, which other records carry, but in no situation do the strings "foo.example.com" or "10.1.0.1" actually go over the network when doing a DNS resolution.


Nitpick: Statically typed, not strongly typed.


Another one to avoid is using a CNAME in the MX. It will work until it doesn't.


Doing a mail server project, you don't want to know how many people have recursive cnames configured on their mx records. At least now I know that ruby has a stack size of over ten thousand.


Jup that one looks like it works for basic test cases but then breaks unexpectedly in the real world. Can't remember the exact problem but I have remembered to never point MX at a CNAME.


The SMTP standard specifies a loop prevention algorithm that ensures that fallback SMTP Relay servers don't end up forwarding back to themselves or even their own fallback servers. This loop prevention relies upon looking at the domain names in the MX resource records, and breaks if such a name is an (unknown by the fallback server itself) alias for the true domain name via a CNAME resource record.


I've been janitoring email for years and have never seen someone put an IP address in an MX record.


raises hand I did that because it worked and nobody told me not to until years later. Not sure if that's an effect of self-teaching or just not properly reading configuration guides (or both), it's about ten years ago now.

And apparently I'm still doing it wrong, I recently learned I'm supposed to point the MX of the various domains to whatever certificate the mail server will use. I thought the mail server just had to have certs for all the domains it wished to serve. Again, though, it worked and nobody told me otherwise until the topic came up a few weeks ago (a friend of mine is building a mail server). Back when I set the thing up, StartCom was still popular, and while I use LE now, I didn't know I had a reason to change configs to better accommodate transport encryption.


> I did that because it worked ...

These things tend to -- until they don't (by which time you don't notice).

> ... and nobody told me not to until years later.

Instead of trying to enumerate all of the wrong ways to do things, the RFCs -- the authoritative documents -- will describe the right way to do things (although, in some cases, they do explicitly identify some things one must not do). If an RFC is ambiguous or unclear, that's a deficiency which should be addressed.

--

> And apparently I'm still doing it wrong, I recently learned I'm supposed to point the MX of the various domains to whatever certificate the mail server will use.

In general, the following has worked quite well for a long time:

1. Choose the "one true name" that your mail server will be known as.

  foo.example.com
2. Create an A RR for the hostname that points to the IP address of the server.

  foo.example.com. -> 192.0.2.25
3. Ensure that the PTR RR for the IP address of the server resolves to the chosen name (cf. "forward-confirmed reverse DNS").

  25.2.0.192.in-addr.arpa. -> foo.example.com
4. Configure your MTA to use foo.example.com as its "official" name (in EHLO/HELO greetings, Received: headers, and so on). If you run POP3/IMAP4 daemons on the same host, configure them to also use the same name.

5. Ensure that the MX RR for any hosted domains reference the one true name.

6. If you wish to use additional hostnames to refer to this server ("mail.example.com", a "mail" subdomain for each of your hosted customer domains, etc.), create CNAME RRs for them that point to the one true name.

7. Acquire and install a certificate for the one true name of the server ("foo.example.com") AND any other names that the server is known by (i.e., any hostnames from step six) and configure your MTA (and POP3/IMAP4 servers) to use it.

--

A few related points:

Notice the common theme: use the "one true name".

The above steps assume that everything is running on a single host that has a single IP address. If it has multiple IP addresses available, you can "get more creative" and use "multiple true names" (this is almost done for "cosmetic" purposes, however; there are no technical reasons to do so).

I did not mention SPF, DKIM, or DMARC, but you'll want to configure them all - and they should all use the "one true name" of your mail server.

Some mail clients nowadays can make use of the "autoconfig" [0] and/or "autodiscovery" [1] methods, eliminating the need for the end user to manually set up their MUA. Additional RRs will need to be created to support these methods; "autoconfig" will also require a web server and some additional configuration.

Postfix added support for SNI a few years ago (I can't speak to other MTAs). As with HTTPS, this allows using multiple "per-domain" certificates instead of a single certificate with all names. I don't know which, if any, mail clients currently support and, I have no firsthand experience using it. I mention it just in case it may be something you want to look into.

--

[0]: https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird...

[1]: https://tools.ietf.org/html/rfc6186


He gathered some data and found 0.06% were doing this.


Which is so little, that I'm surprised that he even bothered to write a blog post about it. Clicking through the links it looks like a lot of the pages are blogspam/secondary language versions of bigger websites, so I doubt that a lot of those webmasters are even trying to have a properly set up MX record (or care about that).


Yeah that percentage is really close to 0%. What are the odds of the 0.06% who do it see this blog post? Let it go.


> Many mail servers are lenient when it comes to this misconfiguration and will deliver mails nevertheless, so this may stay undetected. I happen to use a mail server that is less forgiving (Courier), and every now and then I cannot send a mail due to this.

Sorry man but this sounds like a "you" problem. You probably need to fix your mail server or get a new one.


There's two ideal ways to deal with this:

1. Accept that the new standard is that ip addresses should be supported, and write a new rfc document with that change. 2. Encourage people to not support this.

Simply asking all mailservers to support this non-standard feature (or de facto standard) is arguable the worst outcome, because now every mail server implementer is expected to implement the standard + a bunch of institutional knowledge.

Luckily with mail there's a lot of incentive to set things up correctly, because getting parts of it wrong likely results in a higher number of emails going to spam.


There’s also the option to tell them that “you shouldn’t do it this way, but I’m going to tolerate it ... for now.”

I made up the tongue-in-cheek HTTP 397 for this case:

https://pastebin.com/TPj9RwuZ


The problem with this is if a few popular servers are lenient, people are going to start relying on this lenient behavior.

More people relying on this means more servers will have to start supporting this bug and you end up with the 'worst case' again.

Being strict if you can tolerate it is usually the better option.


I agree. But if all email servers ignore the rfc to cater for real world issues then at some point a new rfc would also make sense.


And here we see someone exemplifying why Gresham's Law trumps Postel's Principle. Bad protocol implementation drives out the good because of exactly this sentiment.


Is it really a sentiment, or a fact? If you want to be strict in what you accept, you have to be ok with rejecting stuff that would work, but isn’t strictly conformant.

You can lament that is the case, but it is just the way it is.


It's valid to choose to use strict standards-conforming software. It's quite arguable that such lenient mail servers are broken in this fashion, since the spec requires a domain (and thus IP addresses are not valid in MX records).


Does someone run a DNS server that will return an IP address directly from the name?

I think once upon a time in-addr.arpa. did this, so you could use http://4.3.2.1.in-addr.arpa/ and it'd resolve to 1.2.3.4. But not now.


I have written a very simple (IPv4/IPv6 addresses only) DNS server which can use Lua to determine the IPs to return to the user (It was my big “do cool open source during the pandemic” project). To implement this particular problem, I whipped up this Lua script:

  -- This script is to be run by coLunacyDNS
  -- This script takes a query like 10.1.2.3.ip4.invalid. and returns the
  -- corresponding IP (e.g. 10.1.2.3 here)

  -- Change these IPs to the actual IPs the DNS server will run on
  bindIp = "127.0.0.1" -- We bind the server to the IP 127.0.0.1
  bindIp6 = "::1" -- Localhost for IPv6

  function processQuery(Q) -- Called for every DNS query received
    if Q.coQtype == 1 then
      local query = Q.coQuery
      if query:match("^%d+%.%d+%.%d+%.%d+%.ip4%.invalid%.$") then
        local ip = query:gsub("%.ip4%.invalid%.$","")
        return {co1Type = "A", co1Data = ip}
      end
    else
      return {co1Type = "notThere"}
    end
    return {co1Type = "notThere"}
  end
One will need coLunacyDNS to run this script:

  git clone https://github.com/samboy/MaraDNS
  cd MaraDNS/deadwood-github/tools/coLunacyDNS
  make
  sudo cp coLunacyDNS /usr/local/bin
Full documentation for coLunacyDNS is available:

https://github.com/samboy/MaraDNS/blob/master/deadwood-githu...


http://xip.io/ does, until it's turned off.


What do you mean turned off?


When using an external service like this one, you have no guarantee:

- this service will last forever

- this service won't be acquired by someone else with evil intention and will never lie

Do not use this service. It has the power to steal your traffic.


It’s also possible to run it yourself, as I point out elsewhere in the thread (complete with the Lua script to run the code).

To summarize:

  git clone https://git.sr.ht/~samiam/MaraDNS
  cd MaraDNS/deadwood-github/tools/coLunacyDNS
  make
  sudo cp coLunacyDNS /usr/local/bin
And the script to do the name-to-IP conversion is one of the examples included in the docs:

https://github.com/samboy/MaraDNS/blob/master/deadwood-githu...


It's not as if it's built into the protocol, operated decentrally and guaranteed to work. Someone generously operates the service. At least that's what I assume GP meant.


in-addr.arpa is for reverse lookups. It is how IPs resolve to names. The address is reversed to allow delegation of IP ranges to DNS servers that are “closer” to the IP address.

Only the absence of a matching in-addr.arpa record would “look up” to the IP itself (by failing to look up to a name).


Sure, the PTR record gives the name. But I seem to remember it also returning A records with the corresponding IP address.



fyi https://news.ycombinator.com/item?id=26216790, this is another registered domain which is generously being ran for free for now. Don't rely on it.


> I happen to use a mail server that is less forgiving (Courier), and every now and then I cannot send a mail due to this. It’s rare, but it does happen. If your mail server has such a configuration you may not receive some legitimate e-mails.

Why not fix Courier? Seems easier than trying to convince others to change how they configure their DNS. Be forgiving in what you accept and disciplined in what you send.


Why not follow the standards? The standard states a MX record contains a domain name that does not point to a CNAME record.

If you don’t follow the standards things might fail. That’s not someone else’s fault, it’s your fault.


In this case, Courier is following the standard and it's failing, and it's the "fault" of the software. Courier is breaking (the aptly named) Postel's Law:

"Be liberal in what you accept, and conservative in what you send."

Courier is failing to be liberal in input-handling.


Postel's law was a good rule of thumb in the early wild west internet. In modern times I think it's largely anachronistic. Being liberal in what you accept leads to security problems, erosion of standards, growth of edge cases, etc.


I don't think anachronistic is the right description, but I agree that in some contexts Postel's law should not be followed.

Postel's law is a good rule of thumb if you're writing a JSON library, but not if you're writing anything that has to do with security.


> Postel's law is a good rule of thumb if you're writing a JSON library, but not if you're writing anything that has to do with security.

I'm a big fan of Postel's law in the context of UNIX tools, but I think that JSON is exactly the wrong example: JSON parsing is a security/format boundary, and I don't want my JSON (or any other parser) trying to suss structure out of something that's under- or unspecified. That way lies input confusion vulnerabilities.


Well, one example is having a JSON object property that is nominally typed as `number` but a JSON parser/library would also accept a number-in-a-string, so both `{ "foo": "123" }` and `{ "foo": 123 }` would be accepted.

Storing numbers inside strings can be necessary if you're encountering JavaScript's 2^56 limit on integers, for example.


> Well, one example is having a JSON object property that is nominally typed as `number` but a JSON parser/library would also accept a number-in-a-string, so both `{ "foo": "123" }` and `{ "foo": 123 }` would be accepted.

This is a great example of "paving over bad behavior with worse behavior."

If JSON is specified to only represent numbers that fit within a JavaScript double, then a correct parser must fail on numeric literals that don't fit into that type. It's up to me as a consumer to interpret strings that represent larger numbers.

I've had this exact kind of "helpful" behavior cause potentially exploitable bugs in programs before: a complex system was using more than one JSON parser, and parser Foo would accept numeric inputs that parser Bar would silently fail on (mangling large numbers into garbage). The result was a potential arbitrary read primitive.


> If JSON is specified to only represent numbers that fit within a JavaScript double,

It isn't / doesn't make that restriction. For example,

  10000000000000000000000000000000000000000000000000000000000000000
  00000000000000000000000000000000000000000000000000000000000000000
  00000000000000000000000000000000000000000000000000000000000000000
  00000000000000000000000000000000000000000000000000000000000000000
  00000000000000000000000000000000000000000000000000000000000000000
  000000000000000000000000000000000000000
is a valid JSON value. Python will decode it to an integer with the equivalent value; JavaScript will decode it to "Infinity", as it exceeds the limits of Number. (Despite nowadays having a bigint type that could represent it.)

It is possible to write a JSON parser in JavaScript that would handle decoding large numbers to BigInts. Most people just don't bother, as it's pretty rare to need to go above the 2 * 53 limit of JS's number.


You're absolutely right about that, and that's even worse than I had remembered! Not only can two parsers not be trusted to have equivalent acceptance contracts (in the absence of bugs), but they can correctly disagree on the acceptance of a single input!

The actual RFC language[1]:

> This specification allows implementations to set limits on the range and precision of numbers accepted. Since software that implements IEEE 754-2008 binary64 (double precision) numbers [IEEE754] is generally available and widely used, good interoperability can be achieved by implementations that expect no more precision or range than these provide, in the sense that implementations will approximate JSON numbers within the expected precision.

[1]: https://tools.ietf.org/html/rfc7159#section-6


I added some newlines to your number because it was borking the page layout. Sorry; it's our bug.


Not so liberal about what you accept, ehe? ;)


We try to make up for it in the extreme narrowness of what we produce.


Are you hiring? <_<


JSON libraries are security-sensitive, though; they tend to get used on content coming from 3rd parties over the internet.


I prefer not having to maintain code that is overly flexible with its input. Last time I ran into half a page of workarounds for bad input I spend a day tracking down all affected files and making sure I could either ignore or fix them. The result was a neat little string comparison that didn't have half a dozen unpredictable edge cases.


Everything has to do with security. Especially message formats like JSON.

Accepting a non-conforming message could easily lead to injection.


It's important to consider each decision. Sometimes it is not fine to be liberal, sometimes it is.

In this case, I'd say that an MX record containing an IP address is not a big deal versus an MX pointing to an A record that contains an IP address, so one may consider that it makes sense to favour successful delivery of emails over strict enforcement of the standard and to accept it. That's pretty much what Postel's law is about and why many servers do accept it (though it also makes sense for a server to refuse to be configured that way even if it accepts it externally for robustness).

Postel's law is not an anachronistic concept. This sort of design consideration applies everywhere in the real world.


It is important to remember what Marc Crispin had to say about this:

> Actually, Postel's principle is misstated. I knew Jon personally. He never advocated forcing implementations to accept bogus protocol, and it is a perverson of Jon's legacy to claim otherwise.

> "Be liberal in what you accept" referred to accepting a wide range of valid protocol, as opposed to accepting only the most common form. If you consider the early protocols, such as Telnet and FTP, it was all too easy to create two compliant and non-interoperable implementations due to each implementation choosing a different subset.

-- https://groups.google.com/g/alt.comp.mail.qmail/c/dcwx0Wc7yp...

> This statement is based upon a terrible misunderstand of Postel's robustness principle. I knew Jon Postel. He was quite unhappy with how his robustness principle was abused to cover up non-compliant behavior, and to criticize compliant software.

-- https://groups.google.com/g/comp.mail.pine/c/E5ojND1L4u8/m/i...


Marc "MM Is Not At Fault" Crispin was also the author of the "infamous" RFC 748: Telnet Randomly-Lose Option.

https://en.wikipedia.org/wiki/Mark_Crispin

https://tools.ietf.org/html/rfc748

   4.  Motivation for the option.

   Several  hosts appear  to provide  random  lossage,  such  as  system
   crashes,  lost data,  incorrectly functioning programs, etc., as part
   of their services.   These services are often undocumented and are in
   general  quite confusing  to the novice  user.   A general  means  is
   needed to allow the user to disable these features.


> "Be liberal in what you accept" referred to accepting a wide range of valid protocol

Have you considered that after some point you need to accept the de facto protocol as a valid protocol?

If everyone else is using unnamed but extant protocol X, why fight that? What do you gain from it?


I think there's some nuance here. Being liberal in what you accept is good for the growth and connectedness of a network. It's so powerful that it's not so much a suggestion as an inevitability -- if you're trying to be perfectly strict, then you will be excluded from the network and other people will find a way to be included. A party will always be bigger when you are less strict about the invitation/rsvp protocol.

But it has obvious downsides. One is that the protocol keeps evolving, because people find novel ways to be non-conforming senders. This means an implementation is never "done". Another is that it becomes so hard to create a new implementation that accounts for all the non-conforming behavior, that the "standard" essentially becomes defined by a few of the big implementations.


I thought about adding that, I should've...

It's widely believed these days that postel's law was a mistake.


Do you want to send people email?

Then you'll need to be liberal in what you accept.


Why can't the other party be conservative in what they send?


> Why can't the other party be conservative in what they send?

Because they don't want to be? Because they don't know that they should be? Because they don't know how? Because they think they are but they're mistaken? Because the specification is ambiguous? Any number of reasons.

But you can't control what they do. You can only control what you do.

If you want to send an email to them, you need to be compatible with their email server.


Go back to reddit. RFCs are standards but real life requires acceptance of divergence from the exact letter of the law.


> Why not follow the standards?

Because they can't send email when they follow the standard?

What are you trying to achieve? Following a standard for the sake of it, or are you actually trying to send email?

And what's the point or use of a standard that people aren't following? What's the point of following such a standard?


No, it’s the other way around. You can’t receive mail from standards-compliant servers if you don’t follow the standard.

What the point is of the standard requiring you to use a name instead of an IP address is a reasonable question but not the same question as whether you should follow the standards.

Note this is a standard made by people who knew what they were doing and it has stood for 35 years. There’s always room for improvement but it would be a bit silly to think you can just handwave it away with arguments you can come up with in a few seconds. There is bound to be a catch.

In this case the catch of course is that there are more address types than IPv4 addresses, so the system requires you to specify what kind of address you are talking about. The mechanism for that is the A record, which only holds IPv4 addresses.


Domain names and IP addresses are interchangeable almost everywhere else right? There already is a standard here and the spec is breaking it, not the other way around.


Not really when it comes to dns. You cant put a domain name in an A record or an ip address in a CNAME.


And that causes problems too right?


Does it? I've never heard anyone complain


Because most dns server software doesn’t accept it. There is no reason to put an IP address in a CNAME record, it’s not easier or more convenient, you just need to change the CNAME record type to ‘IN A’.


That's how I feel. Specific records should not specify if its a domain name or an IP. They both should be accepted.


DNS records are statically typed. An “A” record can only contain an IPv4 address, just like a variable of type “int” in the C programming language only can contain an integer. An MX record, just like CNAME, SRV, and others, can only contain a domain name, not an IP address of any kind. You can input a domain name which looks like an IPv4 address, but this is simply a syntax overlap; it happens to be that the normal textual representation of IPv4 addresses are also valid syntax for an unrelated domain name. Tellingly, the syntax for IPv6 addresses does not overlap with domain names, so you cannot make this error with IPv6 addresses.


So an A record should also hold domain names? Or IPv6 addresses?

In DNS, there is actually a single record type that should hold a physical address, for each supported protocol address. We have A records for IPv4, and AAAA records for IPv6. Anything else should be a domain name.

Adding both IPv4 and IPv6 support to every other record type would be a waste.

Note: ignoring other protocol addresses above to keep it focused on what is currently is large scale use.


I don't think you appreciate how old DNS is or why it uses the data structures it does.


There's a de jure standard (the RFC) and a de facto standard (the real world). The question then becomes whether you want to be right or whether you want to be able to send mail.


>> There is one other special case. If the response contains an answer which is a CNAME RR, it indicates that REMOTE is actually an alias for some other domain name. The query should be repeated with the canonical domain name.

https://tools.ietf.org/html/rfc974 (Page 3)

In general, we expect systems to be forgiving.


Because if you follow the standards, you can't send mail to some destinations, the issue the author is complaining about.

It's the author's "fault" they can't send mail to those destinations when others can.


But does the standard make sense? What's the rationale for not using an IP address?


Because DNS works with many kinds of addresses, not just IPv4, and you shouldn't have to guess what type of address a record holds based on format.

When you see an MX record with the value 1::8, how should you interpret it? Is it a malformed value? Is it an IPv6? Is it some other protocol that you don't know about?

DNS clients shouldn't have to guess. Instead, the MX record should point to a domain name, and the client should look up the corresponding address record for the protocols it knows how to speak (A or AAAA or whatever else will exist).


That is the best most irrefutable answer for why it's impossible I've seen so far. Better than "because it's physically impossible". (Is it electrically prevented at the Physical Layer, otherwise the router would catch fire if you tried to do that?)


To be precise, it’s logically impossible, since MX records are defined by the relevant standards to consist of a number of bytes which are to be interpreted as a priority integer followed by a series of DNS domain name labels. There is no defined way for an MX record to contain an IP address. You could make up some such way, but then it wouldn’t be an MX record as commonly defined, it would be your private extension of the standards.


"The standard definition tells you not to" isn't as deep and complete and useful an explanation as "the standard definition tells you not to, because networking protocols should not have ambiguities or make guesses".

https://en.wikipedia.org/wiki/No_true_Scotsman

To be precise instead of tautological (which you should be when arguing the pedantic nuances of networking protocols), when you use a word like "physically", you're implying that it has something to do with the "Physical Layer", and that there could not exist another networking protocol in the same universe that DID allow IP addresses in MX records, because it's forbidden by the physical laws of nature, not by the logical laws of networking protocols.

It's literally like using the word "literally" to mean "figuratively". (And I mean "literally" literally, not figuratively.)

Obviously it's not physically impossible, because sometimes people do it, and sometimes it even works.

I will agree that it's unwise and scandalous and logically impossible, just not "physically" impossible, and that a better explanation is needed. That's probably why the first reply to your comment was "Out of curiosity though: why is it like this?"

A networking protocol that operates faster than the speed of light, or sends information backwards in time, could be physically impossible, according to the currently known laws of physics.

Although it would be super cool and convenient if you could specify a "Date:" field in the past or the future to send email at the specified time.


You’re right, the word “physical” was badly chosen. Mea culpa.


So was the term "Gish Gallop" that you wrongfully accused me of, so you still owe me a "mea culpa" for that too.

A series of statements needs to be lies in order to qualify for that term, and you totally refused to provide any evidence and failed to prove anything I said was not true, but it was. The fact that Eric S Raymond has provably and publicly said so many many many racists things over the more than three and a half decades that I've personally known him does not make me or WikiQuotes literally quoting a few of them a "Gish Gallop".

https://en.wikiquote.org/wiki/Eric_S._Raymond

Those were all actual ESR quotes, despite your denials and overconfident claims that I was lying and that you could rationalize and explain away them all. Please, in the future, chose your words and heros more carefully, and stick to the facts, instead of making stuff up, and please stop lying and white-knighting in the defense of a virulent racist (and sexist Harvey Weinstein defender) and linking to his personal fundraising page.

Nobody "canceled" you -- quite the opposite: I tried to engage you in a conversation, gave you the facts and citations, asked you to explain yourself, and prove what you claimed, and YOU decided to refuse, despite the fact that you glibly brushed off all his racist statements and wrongly called me a liar by saying "I’m sure all your claims can be either explained as inconsequential or disproven as false" in his defense.

When you lie down with dogs, you get up with fleas.


Dear Don, please don't do flamewars on HN and especially please don't start them up in unrelated threads.

https://news.ycombinator.com/newsguidelines.html


Because you can't send mail everywhere, obviously.

It's nice that it's the other person's fault. Still doesn't make your mail arrive.


Unless I'm missing something, the standard sounds pretty stupid


You're missing something: IPv4 is not the only type of physical address supported by DNS. There is also IPv6, and historically there were others.

Instead of trying to parse the address and guess what protocol it might be, DNS tries to make that unambiguous: you ask it for the A or AAAA records for a domain name you are interested in, and you know for sure that you are getting an IPv4 or IPv6 address respectively.

The only clean alternative would have been to make an MXMXMXMX record type to hold a domain name OR an IPv6 address.


You are missing a lot, including the fact mentioned several times in this discussion that the data portion of an MX resource record simply is not an IP address. The data structure is a wire-format domain name (plus an integer). Even in BIND's "zone" file format, a human-format IP address isn't a fully qualified human-format domain name. But yes, the DNS RFCs are not as good as they could have been. However, you have reached that conclusion by the wrong route. (-:


I’d make the same argument, especially when it concerns smtp or dns as both standards are full of contradictions, caveats, and errata and there are plenty of real world implementations that deviate from the specs.


> Why not fix Courier?

It isn't "broken".


That does seem the better outcome - there’s no downside in being lenient here.

> I did a quick scan of the Alexa Top 1 Million list. Currently around 0,06 % are affected

Only affects a small minority of mailservers, and even then only 0.06% of domains.


> However some mail servers do configure an IP address.

That the interpretation of the MX record is overly pedantic, makes the above statement from the article a wee bit ironic.


I have come across companies who are hosting their mail via a provider (usually cPanel-based) and don't have MX records in their DNS at all; the provider has a failover to route them to the naked domain IP.

Absolutely insane because soon as you change the naked domain IP to point elsewhere, their email stops working.


This is by design.

If an MX RR isn't present, the spec says MTAs are to try to deliver majl to the host that the A RR points at.

If you don't want that, create the appropriate MX RR. If you don't want e-mail for a given domain, create a null record.


Thank, wasn't aware that was in the spec.

Makes sense, unfortunately allows for businesses (generally SMEs) to be relying on very sketchy setups.


I think it is not the providers fault. This is in the spec, if MX record does not exist for a domain try to deliver to the host behind the A record of the domain (naked IP).


With IP addresses, it is not possible to validate TLS certificate as well. This should not work at all.

Also we have HTTPS everywhere, but DKIM is still not supported by most domains. That is a more serious issue and it also covers this as well.


> With IP addresses, it is not possible to validate TLS certificate as well. This should not work at all.

Technically the CA/B forum hasn't outlawed TLS certificates for IP addresses, and a few live ones exist.

https://1.1.1.1 plus https://[2606:4700:4700::1111]/

https://crt.sh/?q=8.8.8.8



You can get an IP address as a SAN, but that doesn't mean much because unless configured to do so, most email servers will not validate and reject invalid certificates on a destination mail server.


  dig myspecialdomainwhatever.com MX
for anyone like me who had to look that up. (And I'm far from competent on DNS matters so please correct if there's a better way)


I run an email forwarding services so I understand mail system quite well.

IMHO, no one seems to use IP in DNS record, probably someone just do quick and dirty and forgot config.

Because when putting IP, when you change your server you have to tell all people to update MX records. So you usually see service use mx1 mx2 style domain.

Nowadays, peolple rarel setup mail server and use 3rd solution and they usually alreayd use domain name in their DNS record.

So this advice is for people who run their own server who really should know their stuff already.


> Notably, according to the respective RFC 1035 the MX record must contain a domain name and may not directly point to an IP address.

Why?


DNS uses a binary format on the wire. MX records are defined as a 16-bit integer followed by a domain name. On the wire a domain name is a series of length prefixed octets or a pointer to another set of octets. IP addresses in A and AAAA are represented as a fixed length series of octets. It's apples and oranges.


Perhaps one should think about why people put IP addresses in there in the first place --- because in an overwhelmingly large number of usages, an IP is perfectly acceptable instead of a domain name (while a domain name is not always acceptable instead of an IP.) In that sense, RFC 1035 is an aberration.


Don't you have to if you use cloudflare to protect your domain?


2 DNS requests per mail is not efficient.

You should recompile Courier!


If you need a way to keep tabs on a bunch of DNS records check out dug: https://github.com/unfrl/dug




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: