PF Rules on domains

Hi there,

I think it's impossible to do but sometimes maybe it's just that I can't see a way to do it ;)
The subject is that I would like to put rules based on domain or sub-domain.
So, not :
pass in from 111.111.0.0/16
but more like :
pass in from somenet.org

So, not possible ?
 
I'm afraid that is not going to work as the domain name usually maps to a single IP-address or no address at all, and the address mapping could change anytime due to DNS updates, load balancing and whatnot. In either case it wont do what you want it to. Also I would refrain from putting host/domain names into /etc/pf.conf as there is a good chance name service is not up and/or reachable at the time when /etc/pf.conf gets loaded during the system boot process.

If your goal is to restrict HTTP access to certain domains, you could use a proxy server like www/squid to implement ACLs based on domain name, URL path, etc, and enforce the use of the proxy server by using pf to block requests bypassing the proxy.
 
Sure it's not going to work like that ;)
It will translate the domain name to an address and then use that single address in the rules.
That's only the idea : all ip that belong to a domain. So 124.145.2.3 translate to john.somenet.org --> rule match. 124.145.5.6 translate to stan.othernet.net --> rule dont match.
It may work if I could enter a command to check that like dig or nslookup + cut/awk. Sure it would slow down rule processing by an order of magnitude but it would be alright.
Squid is a good idea. Usually used to filter on the way out but yes it should filter on the way in aswell. Or haproxy maybe.
Just it would be elegant to use pf ;)
Or pfblockerng can do that ?
 
It will translate the domain name to an address and then use that single address in the rules.
That's only the idea : all ip that belong to a domain. So 124.145.2.3 translate to john.somenet.org --> rule match. 124.145.5.6 translate to stan.othernet.net --> rule dont match.
It may work if I could enter a command to check that like dig or nslookup + cut/awk. Sure it would slow down rule processing by an order of magnitude but it would be alright.
If you really must have it, define a table in /etc/pf.conf like so:
Code:
table <i_hate_you> persist
Make sure you put it in the correct section (order of statements matters). Then you can put a block rule in place that uses the table and later do something like this to fill the table with addresses: (dig|nslookup|host|whatever) | (cut|awk|whatever) | xargs pfctl -ti_hate_you -Ta o_O
Just it would be elegant to use pf ;)
Eh, not really 🤪
 
Hi there,

I think it's impossible to do but sometimes maybe it's just that I can't see a way to do it ;)
The subject is that I would like to put rules based on domain or sub-domain.
So, not :
pass in from 111.111.0.0/16
but more like :
pass in from somenet.org

So, not possible ?
I don't use pf so I can't test this idea, but it might be worth a try to add your subnetwork to /etc/networks. This is assuming that your hostname resolution order is hosts first, dns second, which I'm pretty sure is the default. Just add the line somenet.org 111.111 under the /etc/networks entry for subnet2. If it doesn't work you can easily remove the line later.
 
I don't use pf so I can't test this idea, but it might be worth a try to add your subnetwork to /etc/networks. This is assuming that your hostname resolution order is hosts first, dns second, which I'm pretty sure is the default. Just add the line somenet.org 111.111 under the /etc/networks entry for subnet2. If it doesn't work you can easily remove the line later.
If you happen to know the address of the domain/network in question in advance, it's a bit pointless to use it's name instead, is it not? And a macro definition inside /etc/pf.conf would accomplish the same, while being more elegant.
 
I don't use pf so I can't test this idea, but it might be worth a try to add your subnetwork to /etc/networks. This is assuming that your hostname resolution order is hosts first, dns second, which I'm pretty sure is the default. Just add the line somenet.org 111.111 under the /etc/networks entry for subnet2. If it doesn't work you can easily remove the line later.
Well that assume all network address of 111.111 are the same domain. Wich may be wrong. 111.111.1.12 should be srv1.somenet.org and 111.111.1.13 srv2.myothernet.org. Assuming I have more than one domain.
 
If you happen to know the address of the domain/network in question in advance, it's a bit pointless to use it's name instead, is it not? And a macro definition inside /etc/pf.conf would accomplish the same, while being more elegant.
I cant know the address in advance or it would be trivial to enter rules based on network and/or ip lists.
One problem is that filtering tools are there to filter on destination domains and not on source domains. They can easily filter in on IP or Subnet but not on names.
But, wait, pfblockerng can filter inbound on countries, right ? So anything.domain.cn can be blocked from accessing my lan. Maybe a domain could be configured aswell ? pfblockerng gurus there ?
 
Yes but it will not do that each time a packet want to get in but only once.
Er, what?! Why would it? Once the address(es) is/are in the table, they stay there and get applied each time a rule references that table. The table just doesn't persist between boots, so after restarting the system you need to fill the table again.
Well that assume all network address of 111.111 are the same domain. Wich may be wrong. 111.111.1.12 should be srv1.somenet.org and 111.111.1.13 srv2.myothernet.org. Assuming I have more than one domain.
That's also not a problem if you use a table, as it can contain any mix of single addresses, network blocks and even IPv4 and IPv6 addresses,
 
... The table just doesn't persist between boots, so after restarting the system you need to fill the table again.
...

+1
The refill of the table makes it at least a little more likely that the IP is relevant. Still - this solution is really stymied by the massive use of CDN on the internet. Might be OK if you're wanting to block some static sites. I tried this for awhile (tables) - but gave up and now I just use unbound, squid, etc when I want to list domains. I still use the firewall of course, but it's pretty minimal.
 
Once again, since not very visible without reading all the posts :
pfblockerng can filter inbound on countries, right ?
So anything.domain.cn can be blocked from accessing my lan.
Maybe a domain could be configured aswell ? pfblockerng gurus there ?
 
Once again, since not very visible without reading all the posts :
pfblockerng can filter inbound on countries, right ?
So anything.domain.cn can be blocked from accessing my lan.
Maybe a domain could be configured aswell ? pfblockerng gurus there ?
You are mixing up entirely different concepts here. Blocking by country can be done with a map that knows what IP blocks have been issued within which countries, like geoip. A domain name is nothing like that. You can register a domain name, put up one server say aaa.my.domain in malaysia, a second one bbb.my.domain in tokyo and a third one ccc.my.domain in paris. All three servers could use IP addresses from entirely different IP blocks, issued by different providers and yet all those server IPs belong to the my.domain domain. So how do you want to find out which IP addresses are part of the my.domain domain? Probably the only way would be to recursively list the DNS records of my.domain, and to my knowledge most if not all DNS servers do not allow that. I guess the closest thing you will get is to ask whois about an address you know belongs to whoever you're trying to block and block the entire CIDR block that whois returns. But even then, it's just one network block. Who says the party you're trying to lock out doesn't have others?
 
Probably the only way would be to recursively list the DNS records of my.domain, and to my knowledge most if not all DNS servers do not allow that.
HEY, that's it !
host -l -a somedomain.org dns.somedomain.org | awk '$4=="A" {print $5}'
give me the list of all IPV4 addresses of that domain, 24379 addresses, wich I can enter in the rules.
Of course the DNS server must allow this and this is not always the case.
host -l -a google.com ns1.google.com | awk '$4=="A" {print $5}'
returns 0 address but I dont care of google ;)
 
give me the list of all IPV4 addresses of that domain, 24379 addresses
That means the maintainer of that DNS domain is an idiot. This is a major security leak and any DNS maintainer worth his/her salt would have made this impossible.
 
That means the maintainer of that DNS domain is an idiot. This is a major security leak and any DNS maintainer worth his/her salt would have made this impossible.
Well, that dont means anybody from anywhere can request the DNS like this. I'll check it soon.
 
Hi there,

I think it's impossible to do but sometimes maybe it's just that I can't see a way to do it ;)
The subject is that I would like to put rules based on domain or sub-domain.
So, not :
pass in from 111.111.0.0/16
but more like :
pass in from somenet.org

So, not possible ?

(Basic concept), You can do something like this:
Code:
table <myTable> persist file "/location/myfile.txt"
pass in quick from <myTable>
and add some.host.name or some.domain in your myfile.txt, line separated. When you reload the PF, it will do simple dns query to resolve the host/domain into IP address and automatically add resulting IP into the table. But if the resolve process fail, pf will not reload.

But I don't encourage you to do this since when your server or PF restarts and it fails on resolving the IP, pf will not start. And also I don't think you can do this on large scale deployment, say 1000+ host/domains at once, it will flood your resolver server.

it's always better to have another set of tools/scripts to do the conversion from time to time for you and add resulting IPs into your table file.
 
Back
Top