-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request - resolve IPs to DNS names #75
Comments
FYI: You can set up another service to display this information. I need to think how and where to accurately display this information. BTW: there is already a suitable pull request: #5 |
The current link to whois from an IP address link does not give much usefull information. Mostly it gives the owner information of a complete ip block. What you want to know is if there is a proper mail server behind the ip-address. If it resolves to something funny or does not resolve at all then it is time to start digging (with another tool maybe.) My suggestion is to create a link that will attempt to resolve a domain name from the ip-address and display it as a popup. Opening up a new page is too distracting for a quick check. Note that an ip-address to domain lookup may not come up with the actual domain because there may be hundreds of domains associated with the ip-address. However since the ip-reverse check is very common in determining valid mail servers you may expect that proper mail handlers will set this up in a decent way. |
I made some changes that will do a hostname lookup on server IP and then validate that a reverse lookup for ip-address using the hostname returns the original ip-address. A failing lookup of ip-address match will mark the ip-address - hostname entry as red while a match will mark the entry as green. This is similar to the ip-rev check that mail receivers will perform to spot improper mail senders. common.js static makeIpElement(ip) {
let url = null;
let type = ip.includes(":") && 6 || 4;
switch (type) {
case 4:
url = Common.ipv4_url;
break;
case 6:
url = Common.ipv6_url;
break;
}
let tn = document.createTextNode(ip);
if (url) {
url = url.replace("{$ip}", ip).replace("{$eip}", encodeURIComponent(ip));
let el = document.createElement("a");
el.setAttribute("href", url);
el.setAttribute("target", "_blank");
el.setAttribute("title", "IP address - hostname");
el.appendChild(tn);
this.resolveIp(ip, type)
.then((response) => {
el.innerHTML = el.innerHTML + " - " + response.hostname;
if (response.status == 'valid')
el.setAttribute("class", 'report-result-pass');
else
el.setAttribute("class", 'report-result-fail');
})
.catch(console.log);
return el;
}
else {
this.resolveIp(ip, type)
.then((response) => {
tn.textContent = tn.textContent + " - " + response.hostname;
if (response.status == 'valid')
tn.parentNode.setAttribute("class", 'report-result-pass');
else
tn.parentNode.setAttribute("class", 'report-result-fail');
})
.catch(console.log);
}
return tn;
}
static resolveIp = async (ip, type) => {
const response = await fetch("resolve_ip.php?ip=" + ip + "&type=" + type);
if (response.ok) {
return response.json();
}
}; resolve_ip.php <?php
/**
* Resolve ip-address to hostname and perform reverse lookup to match resolved hostname with ip-address.
* Mail servers should be set up in dns with a dedicated static hostname.
* Flag invalid and non-matching ip-address - hostname pairs.
* @var string $ip
*/
$response = array();
$ip = $_GET['ip'];
$type = $_GET['type'];
// empty $ip parameter is invalid
if (empty($ip))
{
$response['status'] = "invalid";
$response['hostname'] = "hostname lookup invalid";
echo json_encode($response);
exit();
}
// get the hostname by ip
$hostname = gethostbyaddr($ip);
if ($hostname === false)
{
$response['status'] = "invalid";
$response['hostname'] = "hostname lookup failed";
echo json_encode($response);
exit();
}
// lookup dns to get an array of ip_addresses by hostname
switch ($type)
{
case "6":
{
// lookup ipv6
$ip_res = dns_get_record($hostname, DNS_AAAA);
break;
}
case "4":
default:
{
// lookup ipv4
$ip_res = dns_get_record($hostname, DNS_A);
break;
}
}
// invalid if result is not an array
if (! is_array($ip_res))
{
$response['status'] = "invalid";
$response['hostname'] = $hostname;
echo json_encode($response);
exit();
}
// match our input ip with the result ip's. A match returns a valid status
foreach ($ip_res as $entry)
{
if (($type == "6" && isset($entry['ipv6']) && inet_ntop(inet_pton($entry['ipv6'])) == $ip) || (isset($entry['ip']) && $entry['ip'] == $ip))
{
$response['status'] = "valid";
$response['hostname'] = $hostname;
echo json_encode($response);
exit();
}
}
// no match found, return invalid status
$response['status'] = "invalid";
$response['hostname'] = $hostname;
echo json_encode($response);
exit(); |
I will try to implement something like this. At the very least, your php code lacks input parameter validation and access level validation. There are questions to the js code as well. But the main thing is your idea. Thank you. |
To map domains to ISP names |
Probably not one. The hostname will most likely contain the domain name, but does not have to be identical to the domain. If configured correctly, it must not match. For example, gmail email hosts don't even always have the domain part matching. In a recent email with a sender on the gmail server, from the Received header I took this IP address: 209.85.220.41 $ host 209.85.220.41
41.220.85.209.in-addr.arpa domain name pointer mail-sor-f41.google.com.
$ dig +short mx mail-sor-f41.google.com
$ Nothing. Perhaps I misunderstood something and you meant a different check. Could you please share your thoughts? |
I am running with my suggested code for several month's now. It will do a dynamic reverse lookup to get the dns name and then a dns name to ip lookup to verify it matches the original ip-address. Essentially this is the ip-rev check that mail servers perform. In practice you will see many names matching your own mail provider's servers. They will probably look something like mo4-p00-ob.smtp.provider.com where the "provider.com" part is identical. The vast majority of servernames will be from a very small number of providers. A better way to do this is to perform the ip-rev check when processing the incomming reports. Before the ip-rev check, lookup the ip-address in a database table of previously found adresses where you store the full dns name. This will further avoid the overhead of doing the ip-rev checks. In the summary report you can create an option to group all servers matching a common "provider.com" together. Servernames that were not yet assigned to a common provider name will stick out, which is what you want to spot exceptions. A further enhancement could be to collect mx records. Question then is how you would detect a change in mx configurations. Using a big provider list cannot be maintained. The list provided by Williamdes does not contain any of the providers that I commonly see. |
@KlaasBonnema, thank you for your reply. Unfortunately, the method you described does not work for every configuration. The host that sends mail and the host that receives mail may be in different domains. IP addresses in the result of gethostbyaddr -> dns_get_record may not match. A little later I will add the hosts table to the database, but now I'm trying to figure out what host information will be most useful in the Web UI report view dialog. |
"The host that sends mail and the host that receives mail may be in different domains. IP addresses in the result of gethostbyaddr -> dns_get_record may not match." Do you mean that you may not be able to resolve the smtp server ip_address reported by dmarc because it is not accessable by the server that runs dmarc-srg (behind a firewall)? Dmarc-srg unable to do dns resolve requests would indeed block any informational lookup. The smtp server itself behind a firewall is unlikely because it would not be able to do its job. In recent reports I have two ip_addresses that did not pass the ip-rev test. One has a japanese domain name but no matching ip-address. The other does not even resolve to a domain name. Both requests were dmarc rejected. It is easy to identify these two attempts as illegal use of our domain for sending e-mail using a faked ip_address. |
I apologize, I seem to be confused myself in my experiments with rDNS. I guess I need to write tests and check my conclusions on more reports. |
I have currently implemented this functionality as follows:
A request to the server is sent only when the corresponding button is pressed. This is implemented so as not to overload the server with numerous requests if there are many records in the report. Perhaps later requests to the server will be sent as the report page scrolls or something. rDNS and Reverse IP are cached for 24 hours for the current browser tab. Caching on the server is not implemented yet. Ideally, these requests should be cached by DNS resolver installed on the server. |
As for the summary report - I haven't figured out how to do it properly and safely yet. |
This looks really nice !
Can you make the code in order to allow a community plugin to be added for the resolving process ? A class that can be extended could work, I am not sure. Do what is best for you :) PS: For example adding the ISP name: https://github.com/domainaware/parsedmarc/blob/8.17.0/parsedmarc/resources/maps/base_reverse_dns_map.csv |
@williamdes I thank you for your appreciation of this functionality. As for the plugin manager: I like the idea, but the problem is that I have no idea yet how it should be implemented. The ones I googled in a few minutes I didn't like. I am going to familiarize myself with this subject more deeply in the near future. |
Sure! You could provide a php interface file and check that the plug-in implements it. foreach files in plug-in folder |
There is two things I did find frustrating when reading reports today:
I need to have a visual way to find out what service is behind the IP in the report without having to open a ton of tabs
So what about reverse DNS support ?
The text was updated successfully, but these errors were encountered: