Problems with DNS measurements and NSID
Hi! Whatever I try I fail to get the nameserver id. See measurement: https://atlas.ripe.net/api/v1/measurement/1666014/ But there is no NSID in the results: https://atlas.ripe.net/api/v1/measurement/1666014/result/ Am I doing something wrong, or is there a bug? Thanks Klaus
Hi, NSID is in the result, abuf. I see it when I decode the abuf string. To decode abuf string you may use a Python script or so. https://github.com/RIPE-Atlas-Community/RIPE-Atlas-data-analysis "NSID": "tld-berlin-fra1", "OptionLength": 15 If you are using the above script better to download it as txt wget -O 1666014.txt 'https://atlas.ripe.net/api/v1/measurement/1666014/result/?format=txt' cat 1666014.txt | ./scripts/decode_abuf.py -dall -antony On Tue, May 20, 2014 at 11:32:39AM +0200, Klaus Darilion wrote:
Hi!
Whatever I try I fail to get the nameserver id. See measurement: https://atlas.ripe.net/api/v1/measurement/1666014/
But there is no NSID in the results: https://atlas.ripe.net/api/v1/measurement/1666014/result/
Am I doing something wrong, or is there a bug?
Thanks Klaus
Thanks for the hint. Feature Request: Make NSID available in the results (without the need to parse the whole DNS packet). regards Klaus On 20.05.2014 12:52, Antony Antony wrote:
Hi, NSID is in the result, abuf. I see it when I decode the abuf string. To decode abuf string you may use a Python script or so.
https://github.com/RIPE-Atlas-Community/RIPE-Atlas-data-analysis
"NSID": "tld-berlin-fra1", "OptionLength": 15
If you are using the above script better to download it as txt
wget -O 1666014.txt 'https://atlas.ripe.net/api/v1/measurement/1666014/result/?format=txt' cat 1666014.txt | ./scripts/decode_abuf.py -dall
-antony
On Tue, May 20, 2014 at 11:32:39AM +0200, Klaus Darilion wrote:
Hi!
Whatever I try I fail to get the nameserver id. See measurement: https://atlas.ripe.net/api/v1/measurement/1666014/
But there is no NSID in the results: https://atlas.ripe.net/api/v1/measurement/1666014/result/
Am I doing something wrong, or is there a bug?
Thanks Klaus
Feature Request: Make NSID available in the results (without the need to parse the whole DNS packet)
In case you're using Python, you should know that if you use the new parsing library[1] the work of parsing the DNS packet and getting the NSID out is done for you: from ripe.atlas.sagan import Result result = Result("your-JSON-result-blob-here") print(result.responses[0].edns0.options[0].nsid) [1] https://github.com/RIPE-NCC/ripe.atlas.sagan/
Hi Daniel! On 20.05.2014 15:43, Daniel Quinn wrote:
Feature Request: Make NSID available in the results (without the need to parse the whole DNS packet)
In case you're using Python, you should know that if you use the new parsing library[1] the work of parsing the DNS packet and getting the NSID out is done for you:
Actually I tried it today but failed obviously due to my lack of Python. It would be great if you could add an example to the README e.g. with full result parsing: - load the json file from disk - loop over every result (json list) - print some value
from ripe.atlas.sagan import Result result = Result("your-JSON-result-blob-here") print(result.responses[0].edns0.options[0].nsid)
Why do I have to use the responses[0] object? Can there be multiple responses with different nsids? Thanks Klaus
On Tue 20 May 2014 17:08:47 CEST, Klaus Darilion wrote: Hi Daniel! Hi! Actually I tried it today but failed obviously due to my lack of Python. It would be great if you could add an example to the README e.g. with full result parsing: * load the json file from disk * loop over every result (json list) * print some value The full documentation already has a few examples <https://atlas.ripe.net/docs/sagan/#examples> that should be enough to get you going (I’ve just added some more), but here’s a breakdown of what you’re wanting: |from ripe.atlas.sagan import Result my_results_file = "/path/to/file.txt" with open(my_results_file) as results: for result in results.readlines(): parsed_result = Result.get(result) print(parsed_result.origin) | Once you have a |parsed_result|, you have access to all of the properties of that result, which are defined in the full documentation <https://atlas.ripe.net/docs/sagan/#attributes-methods>. Why do I have to use the responses[0] object? Can there be multiple responses with different nsids? In some cases, DNS results /can/ contain multiple responses. In an effort to maintain consistency for all DNS results, we opted to treat all DNS results as if they contain a list of responses — even if that list is of only one response. This makes it easier to write scripts that make use of the object, since you always have a consistent data type in |parsed_result.responses|. I hope that helps!
Hi Daniel, On 20/05/14 17:47, Daniel Quinn wrote:
On Tue 20 May 2014 17:08:47 CEST, Klaus Darilion wrote: In some cases, DNS results /can/ contain multiple responses. In an effort to maintain consistency for all DNS results, we opted to treat all DNS results as if they contain a list of responses — even if that list is of only one response. This makes it easier to write scripts that make use of the object, since you always have a consistent data type in |parsed_result.responses|. I was actually wondering about this myself. What DNS packet would contain multiple responses, considering that the response object relates to the message(s)[1] and not the individual sections. The RFC doesn't explicitly state that a transaction will only contain one message however I can't think of a situation one would send multiple messages. I suspect it is invalid and suspect or would break some implementations one where to try.
Thanks John [1]http://tools.ietf.org/html/rfc1035#section-4
Maybe there's some confusion here, but this multiple response business is all related to the introduction of `resultset` in firmware 4610: https://atlas.ripe.net/docs/data_struct/#v4610_dns When this firmware was introduced it became possible that instead of there being a single "result" property, a "resultset" property would exist containing a list of responses. Rather than have the library act differently for older firmware results, I opted to have a consistent behaviour. As to why this change was introduced in the first place, if there's interest I can ask Philip to respond to the list tomorrow when he's in since this is more of a question of probe behaviour rather than the parser library.
On 20/05/14 18:23, Daniel Quinn wrote:
Maybe there's some confusion here, but this multiple response business is all related to the introduction of `resultset` in firmware 4610:
https://atlas.ripe.net/docs/data_struct/#v4610_dns
When this firmware was introduced it became possible that instead of there being a single "result" property, a "resultset" property would exist containing a list of responses. Rather than have the library act differently for older firmware results, I opted to have a consistent behaviour. As to why this change was introduced in the first place, if there's interest I can ask Philip to respond to the list tomorrow when he's in since this is more of a question of probe behaviour rather than the parser library.
Hi Daniel, OK, I guess it might be to support retrying the query on a failure but I would be keen to get confirmation from Philip. Thanks John
On 2014/05/20 18:36 , john wrote:
On 20/05/14 18:23, Daniel Quinn wrote:
Maybe there's some confusion here, but this multiple response business is all related to the introduction of `resultset` in firmware 4610:
OK, I guess it might be to support retrying the query on a failure but I would be keen to get confirmation from Philip.
The 'normal' mode for DNS queries is that they get sent to one server. So you would get one reply each time the measurement is performed. The exception is when the measurement is to query the probe's local DNS resolvers. In that case, up to three resolvers are queried and you can get as many replies. In the past, each replies would be an independent Atlas result. However, our storage back-end cannot really handle that. So the code was changed that all three replies are grouped into a single Atlas result. Hence, in general, an Atlas DNS result can contain multiple DNS replies. But only if you select the 'use the probe's local resolvers' option. Philip
On 20/05/14 19:29, Philip Homburg wrote:
The 'normal' mode for DNS queries is that they get sent to one server. So you would get one reply each time the measurement is performed.
The exception is when the measurement is to query the probe's local DNS resolvers. In that case, up to three resolvers are queried and you can get as many replies.
In the past, each replies would be an independent Atlas result. However, our storage back-end cannot really handle that. So the code was changed that all three replies are grouped into a single Atlas result.
Hence, in general, an Atlas DNS result can contain multiple DNS replies. But only if you select the 'use the probe's local resolvers' option. Thanks for the clarification Philip. good to know.
Hi Daniel! Thanks. Meanwhile I managed to iterate over the JSON list and print the nsid: import json from ripe.atlas.sagan import DnsResult f=open("dns-from-de-anycast.json","r") data = f.read() jdata = json.loads(data) for d in jdata: print d result = DnsResult.get(d) print(result.responses[0].edns0.options[0].nsid) print "" But the problem is if there was an error during the measurement (eg timeout), then my script terminates: {u'from': u'84.132.219.105', u'msm_id': 1666006, u'timestamp': 1400570732, u'fw': 4610, u'proto': u'UDP', u'af': 4, u'msm_name': u'Tdig', u'prb_id': 2960, u'error': {u'timeout': 5000}, u'src_addr': u'192.168.179.20', u'group_id': 1666005, u'type': u'dns', u'dst_addr': u'194.0.25.16'} Traceback (most recent call last): File "json-file.py", line 11, in <module> print(result.responses[0].edns0.options[0].nsid) IndexError: list index out of range What is the suggested way to find out if a result is valid and exists? Thanks Klaus On 20.05.2014 17:47, Daniel Quinn wrote:
On Tue 20 May 2014 17:08:47 CEST, Klaus Darilion wrote:
Hi Daniel!
Hi!
Actually I tried it today but failed obviously due to my lack of Python. It would be great if you could add an example to the README e.g. with full result parsing:
* load the json file from disk * loop over every result (json list) * print some value
The full documentation already has a few examples <https://atlas.ripe.net/docs/sagan/#examples> that should be enough to get you going (I’ve just added some more), but here’s a breakdown of what you’re wanting:
|from ripe.atlas.sagan import Result
my_results_file = "/path/to/file.txt" with open(my_results_file) as results: for result in results.readlines(): parsed_result = Result.get(result) print(parsed_result.origin) |
Once you have a |parsed_result|, you have access to all of the properties of that result, which are defined in the full documentation <https://atlas.ripe.net/docs/sagan/#attributes-methods>.
Why do I have to use the responses[0] object? Can there be multiple responses with different nsids?
In some cases, DNS results /can/ contain multiple responses. In an effort to maintain consistency for all DNS results, we opted to treat all DNS results as if they contain a list of responses — even if that list is of only one response. This makes it easier to write scripts that make use of the object, since you always have a consistent data type in |parsed_result.responses|.
I hope that helps!
On 21/05/14 10:07, Klaus Darilion wrote: Thanks. Meanwhile I managed to iterate over the JSON list and print the nsid: … But the problem is if there was an error during the measurement (eg timeout), then my script terminates: … What is the suggested way to find out if a result is valid and exists? First of all, i should say thanks for working with us on this. The trouble with a parsing library is that it’s supposed to be able to handle all of the edge cases, but finding them independently is quite difficult. When you post examples to the list of result blobs that act in unexpected ways, this really helps in polishing the parser and making it more intuitive. Given that, and other comments from John regarding error handling for DNS results, I’ve added a little more code to better handle errors, so if you update Sagan to 0.1.12 (or just |git pull|), and re-run your code you’ll find that |result.is_error| is now set to |True| in your case. Additionally, if you pass |on_error=Result.ERROR_FAIL| to the parsing argument, it’ll explode with a |ResultParseError| which you can handle any way you please. So given your example, you could do something like: | result = DnsResult(d) if not result.is_error: # Do stuff | However, there’s likely cases where you might see results that /aren’t/ errors, but still don’t have any responses, or where |edns0.options| is an empty list. Unfortunately, you have to write your code to account for these, since they’re perfectly valid parsings: | result = DnsResult(d) if not result.is_error: for response in responses: if response.edns0: for option in response.edns0.options: print(option.nsid) | Note that I’m not really checking that much here, just looping over (potentially empty) lists. This keeps your code free of checks, and will make sure that it accounts for cases where the number of responses is > 1 or the number of edns0 options is > 1. But please, if you find another result blob that isn’t performing the way you’d expect, please feel free to post it here or send it to atlas-bugs@ripe.net so we can look into it and make sure that Sagan has complete coverage.
participants (5)
-
Antony Antony
-
Daniel Quinn
-
john
-
Klaus Darilion
-
Philip Homburg