10cd9f4ecSchristosEDNS options 20cd9f4ecSchristos============ 30cd9f4ecSchristos 40cd9f4ecSchristosThis example shows how to interact with EDNS options. 50cd9f4ecSchristos 60cd9f4ecSchristosWhen querying unbound with the EDNS option ``65001`` and data ``0xc001`` we 70cd9f4ecSchristosexpect an answer with the same EDNS option code and data ``0xdeadbeef``. 80cd9f4ecSchristos 90cd9f4ecSchristos 100cd9f4ecSchristosKey parts 110cd9f4ecSchristos~~~~~~~~~ 120cd9f4ecSchristos 130cd9f4ecSchristosThis example relies on the following functionalities: 140cd9f4ecSchristos 150cd9f4ecSchristos 160cd9f4ecSchristosRegistering EDNS options 170cd9f4ecSchristos------------------------ 180cd9f4ecSchristos 190cd9f4ecSchristosBy registering EDNS options we can tune unbound's behavior when encountering a 200cd9f4ecSchristosquery with a known EDNS option. The two available options are: 210cd9f4ecSchristos 220cd9f4ecSchristos- ``bypass_cache_stage``: If set to ``True`` unbound will not try to answer 230cd9f4ecSchristos from cache. Instead execution is passed to the modules 240cd9f4ecSchristos- ``no_aggregation``: If set to ``True`` unbound will consider this query 250cd9f4ecSchristos unique and will not aggregate it with similar queries 260cd9f4ecSchristos 270cd9f4ecSchristosBoth values default to ``False``. 280cd9f4ecSchristos 290cd9f4ecSchristos.. code-block:: python 300cd9f4ecSchristos 310cd9f4ecSchristos if not register_edns_option(env, 65001, bypass_cache_stage=True, 320cd9f4ecSchristos no_aggregation=True): 330cd9f4ecSchristos log_info("python: Could not register EDNS option {}".format(65001)) 340cd9f4ecSchristos 350cd9f4ecSchristos 360cd9f4ecSchristosEDNS option lists 370cd9f4ecSchristos----------------- 380cd9f4ecSchristos 390cd9f4ecSchristosEDNS option lists can be found in the :class:`module_qstate` class. There are 400cd9f4ecSchristosfour available lists in total: 410cd9f4ecSchristos 420cd9f4ecSchristos- :class:`module_qstate.edns_opts_front_in`: options that came from the client 430cd9f4ecSchristos side. **Should not** be changed 440cd9f4ecSchristos- :class:`module_qstate.edns_opts_back_out`: options that will be sent to the 450cd9f4ecSchristos server side. Can be populated by edns literate modules 460cd9f4ecSchristos- :class:`module_qstate.edns_opts_back_in`: options that came from the server 470cd9f4ecSchristos side. **Should not** be changed 480cd9f4ecSchristos- :class:`module_qstate.edns_opts_front_out`: options that will be sent to the 490cd9f4ecSchristos client side. Can be populated by edns literate modules 500cd9f4ecSchristos 510cd9f4ecSchristosEach list element has the following members: 520cd9f4ecSchristos 530cd9f4ecSchristos- ``code``: the EDNS option code; 540cd9f4ecSchristos- ``data``: the EDNS option data. 550cd9f4ecSchristos 560cd9f4ecSchristos 570cd9f4ecSchristosReading an EDNS option list 580cd9f4ecSchristos........................... 590cd9f4ecSchristos 600cd9f4ecSchristosThe lists' contents can be accessed in python by their ``_iter`` counterpart as 610cd9f4ecSchristosan iterator: 620cd9f4ecSchristos 630cd9f4ecSchristos.. code-block:: python 640cd9f4ecSchristos 650cd9f4ecSchristos if not edns_opt_list_is_empty(qstate.edns_opts_front_in): 660cd9f4ecSchristos for o in qstate.edns_opts_front_in_iter: 670cd9f4ecSchristos log_info("python: Code: {}, Data: '{}'".format(o.code, 680cd9f4ecSchristos "".join('{:02x}'.format(x) for x in o.data))) 690cd9f4ecSchristos 700cd9f4ecSchristos 710cd9f4ecSchristosWriting to an EDNS option list 720cd9f4ecSchristos.............................. 730cd9f4ecSchristos 740cd9f4ecSchristosBy appending to an EDNS option list we can add new EDNS options. The new 750cd9f4ecSchristoselement is going to be allocated in :class:`module_qstate.region`. The data 760cd9f4ecSchristos**must** be represented with a python ``bytearray``: 770cd9f4ecSchristos 780cd9f4ecSchristos.. code-block:: python 790cd9f4ecSchristos 800cd9f4ecSchristos b = bytearray.fromhex("deadbeef") 810cd9f4ecSchristos if not edns_opt_list_append(qstate.edns_opts_front_out, 820cd9f4ecSchristos o.code, b, qstate.region): 830cd9f4ecSchristos log_info("python: Could not append EDNS option {}".format(o.code)) 840cd9f4ecSchristos 850cd9f4ecSchristosWe can also remove an EDNS option code from an EDNS option list. 860cd9f4ecSchristos 870cd9f4ecSchristos.. code-block:: python 880cd9f4ecSchristos 890cd9f4ecSchristos if not edns_opt_list_remove(edns_opt_list, code): 900cd9f4ecSchristos log_info("python: Option code {} was not found in the " 910cd9f4ecSchristos "list.".format(code)) 920cd9f4ecSchristos 93*7a540f2bSchristos.. note:: All occurrences of the EDNS option code will be removed from the list: 940cd9f4ecSchristos 950cd9f4ecSchristos 960cd9f4ecSchristosControlling other modules' cache behavior 970cd9f4ecSchristos----------------------------------------- 980cd9f4ecSchristos 990cd9f4ecSchristosDuring the modules' operation, some modules may interact with the cache 1000cd9f4ecSchristos(e.g., iterator). This behavior can be controlled by using the following 1010cd9f4ecSchristos:class:`module_qstate` flags: 1020cd9f4ecSchristos 1030cd9f4ecSchristos- :class:`module_qstate.no_cache_lookup`: Modules *operating after* this module 1040cd9f4ecSchristos will not lookup the cache for an answer 1050cd9f4ecSchristos- :class:`module_qstate.no_cache_store`: Modules *operating after* this module 1060cd9f4ecSchristos will not store the response in the cache 1070cd9f4ecSchristos 1080cd9f4ecSchristosBoth values default to ``0``. 1090cd9f4ecSchristos 1100cd9f4ecSchristos.. code-block:: python 1110cd9f4ecSchristos 1120cd9f4ecSchristos def operate(id, event, qstate, qdata): 1130cd9f4ecSchristos if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): 1140cd9f4ecSchristos # Detect if edns option code 56001 is present from the client side. If 1150cd9f4ecSchristos # so turn on the flags for cache management. 1160cd9f4ecSchristos if not edns_opt_list_is_empty(qstate.edns_opts_front_in): 1170cd9f4ecSchristos log_info("python: searching for edns option code 65001 during NEW " 1180cd9f4ecSchristos "or PASS event ") 1190cd9f4ecSchristos for o in qstate.edns_opts_front_in_iter: 1200cd9f4ecSchristos if o.code == 65001: 1210cd9f4ecSchristos log_info("python: found edns option code 65001") 1220cd9f4ecSchristos # Instruct other modules to not lookup for an 1230cd9f4ecSchristos # answer in the cache. 1240cd9f4ecSchristos qstate.no_cache_lookup = 1 1250cd9f4ecSchristos log_info("python: enabled no_cache_lookup") 1260cd9f4ecSchristos 1270cd9f4ecSchristos # Instruct other modules to not store the answer in 1280cd9f4ecSchristos # the cache. 1290cd9f4ecSchristos qstate.no_cache_store = 1 1300cd9f4ecSchristos log_info("python: enabled no_cache_store") 1310cd9f4ecSchristos 1320cd9f4ecSchristos 1330cd9f4ecSchristosTesting 1340cd9f4ecSchristos~~~~~~~ 1350cd9f4ecSchristos 1360cd9f4ecSchristosRun the Unbound server: :: 1370cd9f4ecSchristos 1380cd9f4ecSchristos root@localhost$ unbound -dv -c ./test-edns.conf 1390cd9f4ecSchristos 1400cd9f4ecSchristosIn case you use your own configuration file, don't forget to enable the Python 1410cd9f4ecSchristosmodule:: 1420cd9f4ecSchristos 1430cd9f4ecSchristos module-config: "validator python iterator" 1440cd9f4ecSchristos 1450cd9f4ecSchristosand use a valid script path:: 1460cd9f4ecSchristos 1470cd9f4ecSchristos python-script: "./examples/edns.py" 1480cd9f4ecSchristos 1490cd9f4ecSchristosQuerying with EDNS option ``65001:0xc001``: 1500cd9f4ecSchristos 1510cd9f4ecSchristos:: 1520cd9f4ecSchristos 1530cd9f4ecSchristos root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65001:c001 1540cd9f4ecSchristos 1550cd9f4ecSchristos ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65001:c001 1560cd9f4ecSchristos ; (1 server found) 1570cd9f4ecSchristos ;; global options: +cmd 1580cd9f4ecSchristos ;; Got answer: 1590cd9f4ecSchristos ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33450 1600cd9f4ecSchristos ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3 1610cd9f4ecSchristos 1620cd9f4ecSchristos ;; OPT PSEUDOSECTION: 1630cd9f4ecSchristos ; EDNS: version: 0, flags:; udp: 4096 1640cd9f4ecSchristos ; OPT=65001: de ad be ef ("....") 1650cd9f4ecSchristos ;; QUESTION SECTION: 1660cd9f4ecSchristos ;nlnetlabs.nl. IN A 1670cd9f4ecSchristos 1680cd9f4ecSchristos ;; ANSWER SECTION: 1690cd9f4ecSchristos nlnetlabs.nl. 10200 IN A 185.49.140.10 1700cd9f4ecSchristos 1710cd9f4ecSchristos ;; AUTHORITY SECTION: 1720cd9f4ecSchristos nlnetlabs.nl. 10200 IN NS anyns.pch.net. 1730cd9f4ecSchristos nlnetlabs.nl. 10200 IN NS ns.nlnetlabs.nl. 1740cd9f4ecSchristos nlnetlabs.nl. 10200 IN NS ns-ext1.sidn.nl. 1750cd9f4ecSchristos nlnetlabs.nl. 10200 IN NS sec2.authdns.ripe.net. 1760cd9f4ecSchristos 1770cd9f4ecSchristos ;; ADDITIONAL SECTION: 1780cd9f4ecSchristos ns.nlnetlabs.nl. 10200 IN AAAA 2a04:b900::8:0:0:60 1790cd9f4ecSchristos ns.nlnetlabs.nl. 10200 IN A 185.49.140.60 1800cd9f4ecSchristos 1810cd9f4ecSchristos ;; Query time: 10 msec 1820cd9f4ecSchristos ;; SERVER: 127.0.0.1#53(127.0.0.1) 1830cd9f4ecSchristos ;; WHEN: Mon Dec 05 14:50:56 CET 2016 1840cd9f4ecSchristos ;; MSG SIZE rcvd: 212 1850cd9f4ecSchristos 1860cd9f4ecSchristos 1870cd9f4ecSchristosComplete source code 1880cd9f4ecSchristos~~~~~~~~~~~~~~~~~~~~ 1890cd9f4ecSchristos 1900cd9f4ecSchristos.. literalinclude:: ../../examples/edns.py 1910cd9f4ecSchristos :language: python 192