Tiny Core Linux
Tiny Core Extensions => TCE Talk => Topic started by: Ulysses_ on August 07, 2011, 05:52:26 AM
-
Objective is to block all sites except youtube.com. A firewall only blocks ip's, and youtube ip's are variable. So a proxy is recommended instead, configured to block DNS lookups to anything but youtube.com. But available ram is very limited.
Does an extremely low ram proxy exist for TC? Like 32 MB or even less, with TC in scatter mode?
Can this simple task better be implemented by rebuilding TC after adding a line or two of C code somewhere in the TC sources?
-
1. erase /etc/resolv.conf
2. add youtube.com entry to /etc/hosts
3. success.
-
Good point, thanks.
What if the TC machine is to provide internet access to other machines in a LAN? Is there some low-ram trick to make TC only allow some domain names?
-
DNSMasq can do what you need.
-
What if a link like this (http://209.85.148.104/) is clicked at or otherwise downloaded?
-
That is not a domain name.
-
What if a link like this (http://209.85.148.104/) is clicked at or otherwise downloaded?
iptables is the tool for that job.
-
But you don't know what IPs to allow while blocking all else. If only domain names had one IP each, you'd simply add an iptables allow rule for youtube's IP while iptables is blocking all else. But youtube.com has several IP's and they may change.
Has anyone thought of something like rebuilding dnsmasq with a few more lines of C code so it generates iptables rules after every successful DNS query?
-
You generally use iptables to block incomming connections, not outgoing.
-
You generally use iptables to block incoming connections, not outgoing.
Works for either.
Objective is to block all sites except youtube.com
I believe I have a dnsmasq solution for this. I will test it out and post results.
-
The upstream DNS server for both examples is 192.168.1.2. Execute "dnsmasq -R -C dnsmasq.conf"
Single machine setup:
IP: 192.168.1.128
/etc/resolv.conf
nameserver 127.0.0.1
dnsmasq.conf
server=/youtube.com/192.168.1.2
Client/Server setup:
Server
IP:192.168.1.128
dnsmasq.conf
server=/youtube.com/192.168.1.2
Client
IP: 192.168.1.129
/etc/resolv.conf
nameserver 192.168.1.128
nslookup for a host on any domain other than youtube.com fails. If you need additional details, just ask.
-
Don't forget to include this domain name too: ytimg.com. It is required by youtube.com in order to show videos, so says the NoScript addon:
(http://img685.imageshack.us/img685/1291/image3my.jpg)
-
Don't forget to include this domain name too: ytimg.com. It is required by youtube.com in order to show videos, so says the NoScript addon:
You can just add an additional line to dnsmasq.conf:
server=/ytimg.com/192.168.1.2
-
Are you doing something about the danger of malicious links that specify IP instead of domain name so no dns query is generated?
-
Just had a brainwave. Can dnsmasq associate a fixed IP with youtube.com and ignore upstream dns servers?
-
Are you doing something about the danger of malicious links that specify IP instead of domain name so no dns query is generated?
If you want to permit only youtube IP addresses, then you'll need to be able to determine what those are and use iptables to block all others. You can configure dnsmasq to log DNS queries to a file, then monitor that file with a cron script. Filter out the youtube addresses and create rules for iptables.
Just had a brainwave. Can dnsmasq associate a fixed IP with youtube.com and ignore upstream dns servers?
Yes, but then you'd need to run an http proxy at that IP. The proxy could just do the youtube.com/ytimg.com filter for you then.
-
Just had a brainwave. Can dnsmasq associate a fixed IP with youtube.com and ignore upstream dns servers?
Yes, but then you'd need to run an http proxy at that IP. The proxy could just do the youtube.com/ytimg.com filter for you then.
Doesn't the browser simply replace domain names with IP's without telling the user? EDIT: now I see what you mean, but then we go to potentially high ram proxies.
What's the dnsmasq config so a DNS query to youtube.com always returns 209.85.148.190? That line would be edited every time the IP is abandonded by youtube. The corresponding iptables line would be edited too.
-
Doesn't the browser simply replace domain names with IP's without telling the user?
I'm not sure what you mean.
What's the dnsmasq config so a DNS query to youtube.com always returns 209.85.148.190?
address=/youtube.com/209.85.148.190
Note that you cannot edit /etc/resolv.conf on any system running a DHCP client. Your changes will be overwritten. The DHCP server will have to send the desired nameserver IP.
-
Thanks. Will try dnsmasq and your config later. Hopefully it is as straight forward as it seems and does not require too much study of manuals.
-
Alright, this works fine with the following in bootlocal.sh:
ifconfig eth1 add 192.168.0.1/24
ifconfig eth1 up
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
dnsmasq -R --log-queries -C /home/tc/dnsmasq.conf
And the following in dnsmasq.conf:
address=/youtube.com/209.85.148.190
server=/ytimg.com/192.168.2.1
So choosing one of the ip's of youtube.com works, but you cannot do the same with ytimg.com. If you replace the second line with the following, youtube page loads but video fails:
address=/s.ytimg.com/74.125.77.101
1. How do I get to see the log of dnsmasq? It says --log-queries will log the dns queries, but where is that log stored?
2. What's the rule for iptables so only 209.85.148.190 and 74.125.77.101 can be accessed?
-
Hi Ulysses_
If the log file ends in a .log extension this should find it for you
find /var -iname *.log
[EDIT]: If it's under /var, otherwise try /tmp or /usr
-
Thanks. It seems syslogd is required to be running, after putting this in bootlocal.sh there is now a dnsmasq log in /var/log/messages. Running syslogd as following, the IP's of interest can be isolated.
syslogd -O /dev/stdout | grep dnsmasq | sed ... etc etc
What are the iptables commands to only allow the resulting IP's to be accessible through this gateway?
-
What are the iptables commands to only allow the resulting IP's to be accessible through this gateway?
I've not tested it, but the following might work:
iptables -I INPUT -i eth1 -s 192.168.0/24 -p tcp -j DROP
iptables -I INPUT -i eth1 -s 192.168.0/24 -p tcp -d 209.85.148.190 -j ACCEPT
iptables -I INPUT -i eth1 -s 192.168.0/24 -p tcp -d 74.125.77.101 -j ACCEPT
The iptables man page (http://linux.die.net/man/8/iptables) can help you. Basically, the above says accept incoming tcp packets on eth1 from 192.168.0/24 destined for 209.85.148.190 and 74.125.77.101 but drop everything else.
It seems syslogd is required to be running
You can use the syslog boot code as well, and monitor /var/log/messages.
-
Not working, an IP link like this (http://209.85.148.104/) is still accessible from client machine (put 192.168.0.0/24 instead of your 192.168.0/24 too)
While we are at it, how do you allow IP ranges instead of individual IPs? Relevant IP's seem to be close to each other, maybe rules should be per 8-bit block.
-
Here is what I did in a VM (192.168.1.128) to demonstrate. I am blocking outgoing ICMP packets here, but the principle is the same. Block all packets which match specific parameters, and allow select IP addresses through.
root@box:~# ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=128 time=1.252ms
root@box:~# iptables -I OUTPUT -p icmp -j DROP
root@box:~# ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
ping: sendto: operation not permitted
root@box:~# iptables -I OUTPUT -p icmp -d 192.168.1.1 -j ACCEPT
root@box:~# ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=128 time=1.252ms
root@box:~# ping -c 1 192.168.1.129
PING 192.168.1.129 (192.168.1.129): 56 data bytes
ping: sendto: operation not permitted
how do you allow IP ranges instead of individual IPs?
From the iptables man page:
iprange
This matches on a given arbitrary range of IPv4 addresses
[!]--src-range ip-ip
Match source IP in the specified range.
[!]--dst-range ip-ip
Match destination IP in the specified range.
Also,
Address can be either a network name, a hostname (please note that specifying any name to be resolved with a remote query such as DNS is a really bad idea), a network IP address (with /mask), or a plain IP address. The mask can be either a network mask or a plain number, specifying the number of 1's at the left side of the network mask. Thus, a mask of 24 is equivalent to 255.255.255.0. A "!" argument before the address specification inverts the sense of the address.
-
This masquerading thing required for the gateway must be complicating things a lot more than this example of yours. Is there any good tutorial for iptables?
-
This masquerading thing required for the gateway must be complicating things a lot more than this example of yours. Is there any good tutorial for iptables?
Not exactly. Forwarded packets do not traverse the INPUT chain (http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TRAVERSINGOFTABLES): "INPUT is meant solely for packets to our local host that do not get routed to any other destination."
You can use the FORWARD chain to accomplish your objective.
-
Sorted. Here's the /opt/bootlocal.sh that does it:
ifconfig eth1 add 192.168.0.1/24
ifconfig eth1 up
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -I FORWARD -p tcp -j DROP
dnsmasq --no-resolv --log-queries --conf-file=/home/tc/dnsmasq.conf
syslogd
Here's the script that reads the dnsmasq log and generates iptables rules for every successful dns lookup it finds in the log:
cat /var/log/messages |\
grep ' daemon.debug dnsmasq\[' | grep ' is [1-9]' | sed 's/^.* is //g' |\ # extract IP
for ip in `cat /dev/stdin`; do \
iptables -S FORWARD | grep -c " $ip/32" > /dev/null # test if rule already exists
if [ $? -ne 0 ]; then \
iptables -I FORWARD -p tcp -d $ip -j ACCEPT && \
iptables -I FORWARD -p tcp -s $ip -j ACCEPT && \
echo Allowing $ip \
; fi \
; done
This script has to be called repeatedly in a loop because it can only read the log file and not the pipe output of "syslogd -O /dev/stdout". It fails to read this pipe output and looks as if the data does not flush out all the way to the end of the script, but only to the first command (grep). Is there something wrong with the script?
-
You could replace "cat /var/log/messages" with "tail -f /var/log/messages"
Post a couple "daemon.debug dnsmasq" lines (I can't do that presently) so I can see the format, and I can make some other recommendations.
-
Found the problem, it was that `cat /dev/stdin` was never evaluated because stdin never shows an EOF. So now using "for read ip; do" instead and it works. Provided "stdbuf -o L grep" replaces "grep" to ensure flushing at the end of each line of stdout, and likewise with "sed" and "syslog -O /dev/stdout".
Tail -f will probably need "syslogd -s 0" to prevent log rotation (or does tail -f still work once rotation occurs? ) but surprisingly tail -f is faster than "stdbuf -o L syslogd -O /dev/stdout" which involves no write to disk.
Here are some lines from the log:
Aug 19 01:43:20 box daemon.warn dnsmasq[1190]: overflow: 27 log entries lost
Aug 19 01:43:20 box daemon.debug dnsmasq[1190]: cached www.youtube.com is 209.85.148.190
Aug 19 01:43:21 box daemon.debug dnsmasq[1190]: query[A] www.youtube.com from 192.168.0.3
Aug 19 01:45:19 box daemon.debug dnsmasq[1190]: query[A] www.google.com from 192.168.0.3
Aug 19 01:45:20 box daemon.debug dnsmasq[1190]: query[A] i4.ytimg.com from 192.168.0.3
Aug 19 01:45:20 box daemon.debug dnsmasq[1190]: forwarded i4.ytimg.com to 192.168.2.1
Aug 19 01:45:20 box daemon.debug dnsmasq[1190]: reply i4.ytimg.com is 209.85.148.138