DNS is the control plane of the Internet. Usually DNS is used for good but:

ISC Bind is a de facto a standard of a nameserver. With introduction of Response Policy Zones in the ISC BIND 9.8 it is became a simple task to monitor and contain malware on DNS layer. RPZ is supported on PowerDNS recursor 4.0.0 and later releases. Knot DNS is also partially supports RPZ.
In comparing with traditional network protection solutions a DNS server can handle millions of indicators without performance impact but there were no automated and efficient way to maintain response policy zones on primary DNS servers.
Usually indicators of compromise are distributed in plain text but in different formats and only a few providers of IOCs make them available via RPZ.
ioc2rpz is a custom DNS server which automatically converts indicators (e.g. malicious FQDNs, IPs) from various sources into RPZ feeds and automatically maintains/updates them. The feeds can be distributed to any open source and/or commercial DNS servers which support RPZ, e.g. ISC Bind, PowerDNS. You can run your own DNS server with RPZ filtering on a router, desktop, server and even Raspberry Pi. System memory is the only limitation.
With ioc2rpz you can define your own feeds, actions and prevent undesired communications.
ioc2rpz transforms IOC feeds into response policy zones (RPZ). You can mix feeds to generate a single RPZ or multiple RPZs. Trusted domains and IPs can be whitelisted. ioc2rpz supports expiration of indicators and accordingly rebuilds zones.
The current release supports: local files, files/requests via http/https/ftp and shell scripts to access other resource types. You can use any file format if you can write a REGEX to extract indicators and indicators are separated by newline or/and return carriage chars (/n, /r, /r/n).
You can use ioc2rpz with any DNS server which supports Response Policy Zones e.g. recent versions of ISC BIND, PowerDNS and any commertial DNS server based on these products (e.g. Infoblox, Blue Cat, Efficient IP). A sample bind's configuration file (named.conf) is provided in the cfg folder.
ioc2rpz.gui is a Management Web interface which is developed as a separate project. It is not required to run ioc2rpz.
ioc2rpz supports RPZ distribution over DoT. The SSL listener service is automatically started on port 853 (PortTLS) if a certificate is provided in the configuration (cert). Current implementation has following limitations:
The easiest way to deploy the service is using docker containers on the docker hub. Deployment on Docker How-To you can find in ioc2rpz wiki.
ioc2rpz is available on the Docker Hub. Just look for ioc2rpz. Prerequisites:
sudo docker run -d --name ioc2rpz --log-driver=syslog --restart always --mount type=bind,source=/home/ioc2rpz/cfg,target=/opt/ioc2rpz/cfg --mount type=bind,source=/home/ioc2rpz/db,target=/opt/ioc2rpz/db -p53:53 -p53:53/udp -p853:853 -p8443:8443 pvmdel/ioc2rpz
where /home/ioc2rpz/cfg, /home/ioc2rpz/db directories on a host system.
You can pass a custom configuration file name via-e parameter. E.g. ./cfg/ioc2rpz2.conf
You can deploy ioc2rpz and ioc2rpz.gui using docker compose. The docker-compose.yml file can be found in ioc2rpz.dc repository.
You can run ioc2rpz and ioc2rpz.gui on AWS. For relatively small deployments (several hundreds thousands indicators) even free tier is enough. The video below shows how to setup ioc2rpz and ioc2rpz.gui on AWS using ECS.
ioc2rpz by default reads configuration from ./cfg/ioc2rpz.conf, listens on all network interfaces and saves DB backup in ./db directory. You can change the default values in include/ioc2rpz.hrl.
If you downloaded sources, before running ioc2rpz you have to compile the code with the following command: rebar3 release.
You can start the application by evoking _build/default/rel/ioc2rpz/bin/ioc2rpz start.
ioc2rpz supports management over DNS/TCP or DoT. It is recommended to use DoT or REST API over DNS/TCP. The current version of ioc2rpz does not support a separate management IP/interface. In any case it is highly recommended to create a designated TSIG key (or keys) which will be used for management only. You can turn off management over DNS.
Supported actions:
ioc2rpz-status, class CHAOS, record TXT. e.g.:dig +tcp -y dnsmkey_1:ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA== @127.0.0.1 ioc2rpz-status TXT -c CHAOS
ioc2rpz-reload-cfg, RR Class CHAOS, RR Type TXTioc2rpz-update-tkeys, RR Class CHAOS, RR Type TXTioc2rpz-update-all-rpz, RR Class CHAOS, RR Type TXTzone_name, RR Class CHAOS, RR Type TXT. E.g. full refresh of dga.ioc2rpz can be invoked by:dig +tcp -y dnsmkey_1:ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA== @127.0.0.1 dga.ioc2rpz TXT -c CHAOS
ioc2rpz-terminate, RR Class CHAOS, RR Type TXTsample-zone.ioc2rpz, RR Class IN, RR Type AXFRREST API (port 8443/tcp) is the preffered management interface. For serurity reasons all management traffic must be encrypted and REST API interface is not started if there is no SSL certificate.
Basic HTTP authentication is used to authenticate requests. ManagementTSIG keys are used for request authentication. A TSIG key name is used as the HTTP username and TSIG key as the password. Access to the REST API is restricted with the ACL.
The REST API supports json (default) and text as an output format based on the "Accept" header. E.g.:
curl -i -u "dnsmkey_1:ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA==" --insecure -H "Accept: text/plain" https://127.0.0.1:8443/api/mgmt/update_tkeys
API requests:
/api/v1.0/update/all_rpz - full refresh of all zones./api/v1.0/update/:rpz - full refresh a zone, where :rpz is the zone name./api/v1.0/mgmt/reload_cfg - reload configuration file./api/v1.0/mgmt/update_tkeys - update TSIG keys./api/v1.0/mgmt/terminate - shutdown ioc2rpz server./api/v1.0/feed/:rpz - get content (indicators) of :rpz feed./api/v1.0/ioc/:ioc?tkey=:tkey - check if indicator is blocked by RPZ feeds. An optional param :tkey allows to limit validation to a specific TSIG Key. W/o it the search will be done among all feeds./api/v1.0/cache/sources/clear/all - remove all sources from the hot cache/api/v1.0/cache/sources/clear/:source - remove :source source from the hot cache/api/v1.0/cache/sources/load/all - load all sources to the hot cacheThe configuration is an Erlang file. Every configuration option is an Erlang term so the configuration must comply with Erlang syntax. ioc2rpz does not check the configuration file for possible errors, typos etc. ioc2rpz supports the following configuration parameters:
srv record is used to define server default values. It consists of:
Sample srv record:
{srv,{"ns1.example.com","support.email.example.com",["dnsmkey_1","dnsmkey_2","dnsmkey_3"],["acl_ip1","acl_ip2"]}}.
cert record is used to define a certificate and a private key for DNS over TLS communications. It consists of:
Sample cert record:
{cert,{"cfg/cert.pem", "cfg/key.pem", "cfg/cacerts.pem"}}.
include record allows to split ioc2rpz configuration into multiple files.
Sample include record:
{cert,"cfg/tkeys.include.cfg"}.
TSIG keys are used for authentication and authorization. It is recommended to use different TSIG keys for ioc2rpz management and zones transfers.
key record consist of:
md5, sha256 and sha512 are supported;Sample key record:
{key,{"key_name_1","md5","ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA=="}}.
{key,{"key_name_1","md5","ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA==",["customers","public"]}}.
dnssec-keygen utility can be used to generate TSIG keys. E.g. the command below will generate a TSIG key 512 bits length with "tsig-key" name using MD5 algorithm, and save the key in the files with extensions "key" and "private". A TSIG the key will be the same in the both files.
dnssec-keygen -a HMAC-MD5 -b512 -n USER tsig-key
Please refer "dnssec-keygen" documentation for details.
Whitelists are used to prevent possible errors and blocking trusted domains and IP addresses. The whitelisted IOCs are removed from response policy zones. ioc2rpz does check only exact match, so it will not split or discard a network if a whitelisted IP address is included into a blocked subnet and vice versa. A whitelist is a text file or a feed of text data. Indicators should be separated by newline characters (/n,/r or both /n/r). Whitelists must contain valid FQDNs and/or IP addresses. ioc2rpz supports unlimited count of indicators.
whitelists record consist of:
""), a default REGEX will be used ("^([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"). none is used if no REGEX is required (the source already provides data in the required format).Sample whitelist record:
{whitelist,{"whitelist_1","file:cfg/whitelist1.txt",none}}.
A source is a feed of malicious indicators. FQDNs, IPv4 and IPv6-addresses are supported. A source is a text file or a feed of text data. Indicators should be separated by newline/carriage return characters (/n,/r or both /r/n). ioc2rpz supports unlimited count of indicators.
source record consist of:
""), a default REGEX will be used ("^([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"). none is used if no REGEX is required (the source already provides data in the required format).
Optional parameters (all or none must be used):Sample source record:
{source,{"blackhole_exp","http://data.netlab.360.com/feeds/dga/blackhole.txt","[:AXFR:]","^([A-Za-z0-9][A-Za-z0-9\-\._]+)\t.*:00\t([0-9: -]+)$"}}.
{source,{"base.rpz1","shell:/usr/bin/dig -y KEYNAME:TSIGKEY @54.69.93.185 base.rpz.infoblox.local axfr | /bin/grep -e CNAME | /bin/grep -v '*.' | /usr/bin/awk -F '.base.rpz' '{print $1}'","",none}}.
Source shell: is used to extend ioc2rpz connectivity options which are natively a bit limited. The ioc2rpz container includes dig, grep, awk and python. E.g. you can mix different RPZ feeds or fetch data from a database.
RPZ term defines a response policy zone.
rpz record consist of:
true or false. true defines that the RPZ should be cached, false - non cached, live zone sources are downloaded and an RPZ generated by AXFR request. "Live" zones do not support incremental zone transfer. if RPZ feed is not cached anyway it is temporary stored into a hot cache. In case if a request timeouts from a client, we will be able to respond next time. AXFR time will be used to determine cache life;true or false. Defines if wildcard rules should be generated;nxdomain, nodata, passthru, drop, tcp-only, {"redirect_domain","example.com"}, {"redirect_ip","127.0.0.1"} and list of local records [{"local_aaaa","fe80::1"}, {"local_a","127.0.0.1"}, {"local_cname","www.example.com"}, {"local_txt","Text Record"}]. redirect_domain is an alias for local_cname. redirect_ip is an alias for local_a, local_aaaa;mixed, fqdn, ip. It is used for optimization.Sample rpz record:
{rpz,{"zone_name",soa_refresh, soa_update_retry,soa_expire,soa_nxdomain_ttl,"cache","wildcards","action",["key1","key2"],"Zone_type",AXFT_Time, IXFR_Time,["source1","source2"],["notify_ip1","notify_ip2"],["whitelist_1","whitelist_2"]}}.
{rpz,{"zone_name",soa_refresh, soa_update_retry,soa_expire,soa_nxdomain_ttl,"cache","wildcards","action",["key1","key2",{groups,["group1","group2"]}],"Zone_type",AXFT_Time, IXFR_Time,["source1","source2"],["notify_ip1","notify_ip2"],["whitelist_1","whitelist_2"]}}.
{rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1","dnsproxykey_2"],"mixed",86400,3600,["small_ioc","blackhole","bot.list"],[],["whitelist_1","whitelist_2"]}}.
{rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1","dnsproxykey_2",{groups,["public","ip2"]}],"mixed",86400,3600,["small_ioc","blackhole","bot.list"],[],["whitelist_1","whitelist_2"]}}.
{srv,{"ns1.rpz-proxy.com","support.rpz-proxy.com",["dnsmkey_3"],["127.0.0.1","10.42.0.10"]}}.
{cert,{"cfg/ioc2rpz_dot.crt", "cfg/ioc2rpz_dot.key", ""}}.
{key,{"dnsproxykey_1","md5","apXqLsDs90H213eV6LS9ryYp5tY8YTpkttOkRCve7dp1Zeob3SGAbaVU9BShpsW25MmR8mTiX5OY0Qetv977Yw=="}}.
{key,{"dnsproxykey_2","sha512","03uuaGl9kqfenjRgIeCv6e29lVvMwviB1+cDX1I0jcVOcTU4jWFwRkfo3ULRMD+NGDfwzYvXkJ94FNEaAW4vzw=="}}.
{key,{"dnsmkey_3","sha512","03uuaGl9kqfenjRgIeCv6e29lVvMwviB1+cDX1I0jcVOcTU4jWFwRkfo3ULRMD+NGDfwzYvXkJ94FNEaAW4vzw=="}}.
{whitelist,{"whitelist_1","file:cfg/whitelist1.txt",none}}.
{whitelist,{"whitelist_2","file:cfg/whitelist2.txt",""}}.
{source,{"small_ioc","file:cfg/small_ioc.txt","[:AXFR:]","^(?!host)(?!ip)\"?\'?([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"}}.
{source,{"dns-bh","http://mirror1.malwaredomains.com/files/spywaredomains.zones","[:AXFR:]","^zone \"([A-Za-z0-9\-\._]+)\".*$"}}.
{source,{"cryptolocker","http://data.netlab.360.com/feeds/dga/cryptolocker.txt","[:AXFR:]","^(?!host)(?!ip)\"?\'?([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"}}.
{source,{"tor-exit","https://torstatus.blutmagie.de/ip_list_exit.php/Tor_ip_list_EXIT.csv","[:AXFR:]",none}}.
{rpz,{"localdata.ioc2rpz",7202,3600,2592000,7200,"false","true",[{"local_aaaa","fe80::1"},{"local_a","127.0.0.1"},{"local_a","127.0.0.2"},{"local_a","127.0.0.3"},{"local_a","127.0.0.4"},{"local_cname","www.example.com"},{"local_txt","Text Record www.example.com"},{"local_txt","Text Record 2"}],["dnsproxykey_1", "dnsproxykey_2"],"mixed",30,30,["small_ioc"],[],["whitelist_1","whitelist_2"]}}.
{rpz,{"dga.ioc2rpz",7202,3600,2592000,7200,"true","true","nodata",["dnsproxykey_1","dnsproxykey_2"],"fqdn",172800,3600,["cryptolocker"],[],[]}}.
{rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1", "dnsproxykey_2"],"mixed",86400,3600,["small_ioc","dns-bh","cryptolocker"],[],["whitelist_1","whitelist_2"]}}.
{rpz,{"dns-bh.ioc2rpz",7202,3600,2592000,7200,"true","true","nxdomain",[],"mixed",86400,3600,["dns-bh"],[],["whitelist_1","whitelist_2"]}}.
{rpz,{"tor-exit-ip.ioc2rpz",7202,3600,2592000,7200,"false","true","nxdomain",["dnsproxykey_1","dnsproxykey_2"],"ip",172800,0,["tor-exit"],[],[]}}.
include/ioc2rpz.hrl contains pre-compiled parameters.
Standard parameters:
MGMToDNS (true/false) - enabled management over DNS/TCP;DBStorage (ets) - defines DB storage for AXFR and IXFR caches. Current version supports ETS only;SaveETS (true/false) - defines if ETS AXFR/IXFR tables should be saved on disk;Port (numerical value, 1 - 65535) - defines a DNS port on which service is running;PortTLS (numerical value, 1 - 65535) - defines a DoT port on which service is running;PortREST (numerical value, 1 - 65535) - defines a HTTPs port on which service is running;TTL (numerical value, in secodns) - default TTL for DNS records/RPZ rules.DefConf (string) - default configuration file;DefDB (string) - default database path;logTS - if defined timestamp is added in log messages;debug - if defined debug log messages are printed;Optimization parameters:
DNSPktMax (numerical value, 100 - 65535) - maximum packet size. Recommended values:
Compression (numerical value, 0 - 9) - Compression level (0 - no compression, 9 - highest compression). AXFR cache and tables on a disk store compressed data;ZoneRefTime (numerical value, in milliseconds) - defines zone refresh check interval;TCPTimeout (numerical value, in milliseconds) - defines TCP session timeout;HotCacheTime (numerical value, in seconds) - Hot cache time for IOCs, Rules, Packets. Live zones are stored in a hot cache;HotCacheTimeIXFR (numerical value, in seconds) - Hot cache time for IXFR IOCs in a hot cache. By default IXFR indicators are cached for a minute (even if it set to 0) because current serial is always rounded to a previous minute.All IOCs, Rules, Packets including live RPZs are stored in the hot cache. Pre-compiled parameters HotCacheTime, HotCacheTimeIXFR define storage time.
The author assumes no responsibility or liability for an
Content type
Image
Digest
sha256:3ffb21369…
Size
85.3 MB
Last updated
3 months ago
docker pull pvmdel/ioc2rpz_dev