Forum Discussion
Need help with DNS iRULE
Hello All,
I have been asked to create an iRULE which will redirect traffic from specific internal VM to external specific IP/DNS. This is only for outbound.
So I had a rule as follows:
when CLIENT_ACCEPTED {
if { [IP::addr [IP::local_addr] equals 10.13.7.0/24] }{
Uncomment the line below to turn on logging.
log local0. "access not allowed: [IP::local_addr] - reject traffic"
reject
} else {
if { ( [IP::addr [IP::client_addr] equals x.x.x.x ] || [IP::addr [IP::client_addr] equals y.y.y.y ] || [IP::addr [IP::client_addr] equals w.w.w.w ] || [IP::addr [IP::client_addr] equals t.t.t.t ]) && [IP::addr [IP::local_addr] equals ] || [IP::addr [IP::local_addr] equals ] } {
if { [matchclass [TCP::local_port] equals Public_DMZ_TCP_port_dg ] || [matchclass [UDP::local_port] equals Public_DMZ_UDP_port_dg] } {
if { [matchclass [UDP::local_port] equals udp_port_dg] } {
snat using this source address
snatpool Public_internet_pool
log local0. "SNATed, [IP::client_addr]:[TCP::client_port] --> [IP::local_addr]:[TCP::local_port]"
Exit this event to avoid disabling SNAT below
return
}
}
}
}
Default action is to not SNAT
snat none
log local0. "Not Allowed to SNATed , [IP::client_addr]:[TCP::client_port] --> [IP::local_addr]:[TCP::local_port]"
}
So as you can from above if I fix the external IP it might not work as external source may change their IP and this rule also needs to change with is.
So I was wondering is there anyway I can do DNS query?
I have looked at
when DNS_REQUEST {
if { [IP::addr [IP::remote_addr] equals 192.168.1.0/24] && ([DNS::question name] equals "www.mytest.com") } {
DNS::answer insert "[DNS::question name]. 111 [DNS::question class] [DNS::question type] 192.168.1.200"
DNS::return
} else ( discard }
}
But not sure how I can integrate my rule and DNS.
Can someone here please help me with this.
Thanks
2 Replies
- Kevin_Stewart
Employee
So if I understand you correctly, you want to allow or limit outbound access to some specific site, but based on external name resolution, that site's IP information might change and you'd have to keep updating your iRule. If that's a correct assessment, then you might have a few options.
First, the DNS_REQUEST iRule you're listing could be used on a GTM, and LTM with DNS services licensed, and if clients were pointing to this VIP for either authoritative (GTM) DNS, or as a load balancing VIP (LTM) for other DNS servers.
Now, you could technically perform a RESOLVE::lookup command on each client request to get the current list of IP addresses for a given site, but 1) you'd need to be able to see the Host name in the request, which means you'd need to decrypt and re-encrypt the outbound traffic, and 2) that might add significant load.
Perhaps more realistically you could create a monitor script tied to a dummy pool that could periodically check the IP addresses, and then update a local datagroup if they've changed.
- Kevin_Stewart
Employee
You think you will be give me direction how to create this monitoring pool?
Thought you'd never ask. 😉
The idea here is that you'd create a Bash script, tie that to an External monitor, and then bind the monitor to a "dummy" pool (a pool with some bogus IP addresses). This does two things: 1) it creates a "cron-like" mechanism for the script, and 2) it can get backed up in normal config archiving. The monitor script will periodically query an external DNS for a defined service name, create a hash of the result, compare that hash to an existing hash (stored in a separate local file), and if the hash is the same it'll do nothing, otherwise it'll update the datagroup with the new IPs and rewrite the hash value file. You need to modify the variables at the top (DNS_SERVER, DNS_NAME, DNS_HASH, and DATAGROUP) to reflect your local environment. You also need to pre-create the address-based data group.
!/bin/bash DNSMONITOR Purpose: to periodically query a remote DNS server for a given name to keep a local internal data group populated with current IP information. define DNS server DNS_SERVER=10.80.0.200 define server name DNS_NAME=tester.mydomain.com define dns hash file DNS_HASH=dns.hash define internal data group DATAGROUP=my_dns_datagroup perform the DNS query lookup=( $(dig @$DNS_SERVER $DNS_NAME +short +time=3|sort) ) verify that the DNS query returned a response if [ $lookup == ";" ] then logger -p local0.info -t DNSMONITOR "DNS monitor is unable to query the DNS server $DNS_SERVER for the name '$DNS_NAME'" exit fi create a flat list of IPs iplist=`printf -- '%s ' "${lookup[@]}"` create a hash of the results hash=`echo $iplist | md5sum |sed 's/ //' |sed 's/-//'` if the hash file doesn't exist or hash file value is different - update the datagroup if [ ! -f $DNS_HASH ] || [ "$(cat $DNS_HASH)" != $hash ] then overwrite the datagroup tmsh modify ltm data-group internal $DATAGROUP records replace-all-with { $iplist } log that the datagroup changed logger -p local0.info -t DNSMONITOR "DNS datagroup was updated with the following values: { $iplist }" create/overwrite hash file echo $hash > $DNS_HASH fi
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com