Using dnsmasq/iptables to redirect DNS/HTTP traffic on Tomato

plexconnect

#1

For those running a tomato router (and probably all other router distros based on dnsmasq) this should be helpful :)

 

This is a method using dnsmasq to do the DNS rewrite on the router and redirecting trailers.applecom traffic to your router, which then snarfs off that traffic and rewrites it to another server on any port based on the source IP (your ATV).

 

For my setup this means:

 

- no root required to run PlexConnect

- no port conflicts on 53/80 on my OS X Server (can disable DNS and change the HTTP port)

- no modifications to ATV at all

 

My environment:

 

- 172.16.32.1 = router (Tomato)

- 172.16.32.2 = server (OS X server, static IP, running PlexConnect)

- 172.16.32.12 = atv (static DHCP)

 

1) DNS setup

 

On the router, go to Advanced -> DHCP/DNS and enter the following line to rewrite trailers.apple.com to your router IP

 

  address=/trailers.apple.com/172.16.32.1

 

2) Rewrite traffic coming from the ATV to your router to a new destination, for me, my OS X server

 

Go to Admin -> Scripts and add this to the Firewall tab. You can reload this script by just hitting Save on the Port Forwarding section somewhere.

 

  iptables -t nat -A PREROUTING -s 172.16.32.12 -d 172.16.32.1 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 172.16.32.2:8090
 
This will only rewrite traffic from the ATV (.12) to the router (.1) on ports 80/443 (HTTP/HTTPS) and rewrite it to the server (.2) on port 8090.
 
HTTPS isn't required, I just put that in there in case one day it is necessary. It doesn't hurt.
 
3) Disable the PlexConnect DNS server (optional, but recommended for this setup)
 
Edit Settings.cfg and change 'enable_dnsserver' to 'False'
 
4) Change the port that PlexConnect runs on (optional if you don't have a port conflict)
 
Option 1: Edit WebServer.py and change the line
 
  server = HTTPServer(('',80), MyHandler)
 
to reflect a different port. If you use a port >1024, you won't have to run as root.
 
Option 2: I also have the change made on my fork and a pull request to iBaa on github to allow changing the ip/port via Settings.cfg.
 
  Commit: https://github.com/wojo/PlexConnect/commit/58205869d70a7cfaf4be85af69ac4b409744eef6
  Pull request: https://github.com/iBaa/PlexConnect/pull/44
 
UPDATE: I see another person that has a pull request to do basically the same thing (https://github.com/iBaa/PlexConnect/pull/42). No idea which one is better as I'm not a Python guy. Either one works it seems!
 
In my situation, I use:
 
  ip_httpserver = 
  port_httpserver = 8090
 
HTH!
 
-- wojo


#2

This is so cool! I started looking into this as well, since I'm also a Tomato user, but I got stuck on the iptables rule. Thanks for sharing and writing up this nice tutorial!!


#3

Yeah nice clear guide and it should allow advanced setups more flexibility.
Btw the pull requests on Github are not being ignored, there is just a lot going on but they will be dealt with.
:)


#4

Just be aware that this - as I understand it - reroutes ALL requests to trailer.apple.com, no matter which device is requesting access.

Following this, there is NO way out to trailers.* any more - meaning any patch to re-enable this app on aTV (or the PMS plugin on that matter) would fail...


#5

Just be aware that this - as I understand it - reroutes ALL requests to trailer.apple.com, no matter which device is requesting access.

Following this, there is NO way out to trailers.* any more - meaning any patch to re-enable this app on aTV (or the PMS plugin on that matter) would fail...

Hmm, that's not how I read it.  I think it only pertains to the traffic from your Apple TV to trailers.apple.com but I plan on testing this out tonight.

Wojo - two quick questions if you don't mind....

1.) Do I just add the IP address of a second Apple TV on a separate Firewall script?

2.) Would you know how to redirect all MLB.tv traffic to unblock-us without putting it in the Tomato DNS config?  

Thank you!


#6

So it *does* redirect *all* traffic to my router (192.168.0.1).  Sorry for doubting you Baa!


#7

It does indeed redirect all traffic to trailers.apple.com to the router because of the dnsmasq config. There isn't a way there to feed the address based on the source IP or anything like that. However, there are more things that are possible.

Here's an example without ATV modifications to DNS and still runs them on non-priv ports. 

When presented with multiple options (1a, 1b) just do one of them.

1a) Intercept DNS traffic to trailers.apple.com and redirect to the PlexConnect DNS server on a different port with dnsmasq

Add this to your dnsmasq config to redirect DNS queries for trailers.apple.com to a different host and port (keeps it out of the way of my existing DNS servers on port 53):

  server=/trailers.apple.com/172.16.32.2#8053

This delegates DNS resolving for trailers.apple.com to PlexConnect which can decide how to go about serving it up.

WARNING: A loop is possible though if PlexConnect tries to query for trailers.apple.com

1b) Intercept DNS traffic to trailers.apple.com and redirect to the PlexConnect DNS server on a different port with iptables

 
Add this to the firewall config:
 

  iptables -t nat -A PREROUTING -s 172.16.32.12 -d 172.16.32.1 -p udp --dport 53 -j DNAT --to-destination 172.16.32.2:8053

This will grab traffic headed to the router from the ATV and redirect to PlexConnect. This will avoid a loop if the PlexConnect box does a lookup for trailers.apple.com unlike method 1a.

This should be nearly identical to changing the DNS on the ATV except it can be directed to PlexConnect DNS running on any port.

2) Patch DNSServer.py to change the bind on port 53 for DNS to another port

Since we will be using the DNS server in PlexConnect for the ATV, but on a different port, edit DNSServer.py and change 

  DNS.bind(('',53))

to something like this

  DNS.bind(('',8053))

If this ends up useful it may be a good idea to make this a config like ip_server and port_server are.

3a) Redirect traffic headed to port 80 on the Plex Server from the ATV to another port (this is for OS X Lion or higher)

I don't have time to write up the entire thing nicely (so it survives reboots, etc), but basically you can add this to pf (the packet firewall) and it'll grab incoming HTTP traffic and send it to another port. See http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/ for instructions on how to make this auto-run on reboot and such.

Edit /etc/pf.conf and add this line near the rdr-anchor line:

  rdr on en0 inet proto tcp from 172.16.32.12 to any port www -> 127.0.0.1 port 8090
 
Enable and reload pf with:
 
  pf -E -f /etc/pf.conf
 
This redirects incoming traffic from the ATV to the local 8090 port. 
 
3b) Redirect traffic on the local Apache server to the Plex Server using a reverse proxy
 
Someone else has instructions for this already using a vhost I believe. Pretty easy.
 
-- 
 
Anyway, there are probably a few more options out there :)
 
A few more things are possible by allowing the DNS server in PlexConnect to advertise a different IP from IP_Self (the router). This would let you put the firewall rule on the router consolidating rules and keeping things tidy.
 
At that point I would really want to get this on the Tomato router and not have anything run on my OS X server keeping PMS on the server (or NAS, desktop, etc) and PlexConnect plus these rules on the router. That way PlexConnect could just use IP_Self, everything would be in one place, etc.
 
Perhaps that's what I'll do soon. My initial run had an error in multiprocessing. Not sure if semaphores work on Tomato (tried mounting /dev/shm as a tempfs and such. Hmm).

#8

Hmm, that's not how I read it.  I think it only pertains to the traffic from your Apple TV to trailers.apple.com but I plan on testing this out tonight.

Wojo - two quick questions if you don't mind....

1.) Do I just add the IP address of a second Apple TV on a separate Firewall script?

2.) Would you know how to redirect all MLB.tv traffic to unblock-us without putting it in the Tomato DNS config?  

Thank you!

1) That's probably the easiest

2) I'm not familiar with unblock-us and what is necessary to do that.


#9

>> Not sure if semaphores work on Tomato

Seems simliar to other NASs. There is an issue open in github...


#10

Wojo

It does indeed redirect all traffic to trailers.apple.com to the router because of the dnsmasq config. There isn't a way there to feed the address based on the source IP or anything like that. However, there are more things that are possible.

 

Here's an example without ATV modifications to DNS and still runs them on non-priv ports. 

 

When presented with multiple options (1a, 1b) just do one of them.

 
1a) Intercept DNS traffic to trailers.apple.com and redirect to the PlexConnect DNS server on a different port with dnsmasq

 

Add this to your dnsmasq config to redirect DNS queries for trailers.apple.com to a different host and port (keeps it out of the way of my existing DNS servers on port 53):

 

  server=/trailers.apple.com/172.16.32.2#8053

 

This delegates DNS resolving for trailers.apple.com to PlexConnect which can decide how to go about serving it up.

 

WARNING: A loop is possible though if PlexConnect tries to query for trailers.apple.com

 
1b) Intercept DNS traffic to trailers.apple.com and redirect to the PlexConnect DNS server on a different port with iptables

 

Add this to the firewall config:

 

  iptables -t nat -A PREROUTING -s 172.16.32.12 -d 172.16.32.1 -p udp --dport 53 -j DNAT --to-destination 172.16.32.2:8053

 

This will grab traffic headed to the router from the ATV and redirect to PlexConnect. This will avoid a loop if the PlexConnect box does a lookup for trailers.apple.com unlike method 1a.

 

This should be nearly identical to changing the DNS on the ATV except it can be directed to PlexConnect DNS running on any port.

 
2) Patch DNSServer.py to change the bind on port 53 for DNS to another port

 

Since we will be using the DNS server in PlexConnect for the ATV, but on a different port, edit DNSServer.py and change 

 

  DNS.bind(('',53))

 

to something like this

 

  DNS.bind(('',8053))

 

If this ends up useful it may be a good idea to make this a config like ip_server and port_server are.

 
3a) Redirect traffic headed to port 80 on the Plex Server from the ATV to another port (this is for OS X Lion or higher)

 

I don't have time to write up the entire thing nicely (so it survives reboots, etc), but basically you can add this to pf (the packet firewall) and it'll grab incoming HTTP traffic and send it to another port. See http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/ for instructions on how to make this auto-run on reboot and such.

 

Edit /etc/pf.conf and add this line near the rdr-anchor line:

 

  rdr on en0 inet proto tcp from 172.16.32.12 to any port www -> 127.0.0.1 port 8090

 

Enable and reload pf with:

 

  pf -E -f /etc/pf.conf

 

This redirects incoming traffic from the ATV to the local 8090 port. 

 
3b) Redirect traffic on the local Apache server to the Plex Server using a reverse proxy

 

Someone else has instructions for this already using a vhost I believe. Pretty easy.

 

-- 

 

Anyway, there are probably a few more options out there :)

 

A few more things are possible by allowing the DNS server in PlexConnect to advertise a different IP from IP_Self (the router). This would let you put the firewall rule on the router consolidating rules and keeping things tidy.

 

At that point I would really want to get this on the Tomato router and not have anything run on my OS X server keeping PMS on the server (or NAS, desktop, etc) and PlexConnect plus these rules on the router. That way PlexConnect could just use IP_Self, everything would be in one place, etc.

 

Perhaps that's what I'll do soon. My initial run had an error in multiprocessing. Not sure if semaphores work on Tomato (tried mounting /dev/shm as a tempfs and such. Hmm).




Do you want to update your guide to include the install and running of PlexConnect on a Tomato router?


#11

1) DNS setup

 

On the router, go to Advanced -> DHCP/DNS and enter the following line to rewrite trailers.apple.com to your router IP

 

  address=/trailers.apple.com/172.16.32.1

 

 

 

When you dont need to redirect to other ports and use that firewall stuff i guess that IP at the end should become the server where plexconnect is running and not your router, right?


#12

hey i have a question is it possible to let a friend connect to my server ? if i use this method.

I'm using iBaa's method now but nobody can connect to my server.

 


#13

1) DNS setup

 

On the router, go to Advanced -> DHCP/DNS and enter the following line to rewrite trailers.apple.com to your router IP

 

  address=/trailers.apple.com/172.16.32.1

 

 

 

When you dont need to redirect to other ports and use that firewall stuff i guess that IP at the end should become the server where plexconnect is running and not your router, right?

Hi tcviper!

Yes, that's correct, and if you set this in your router, you can disable the PlexConnect DNS server.


#14

And where to enter this line on a Asus Rt-n16?


#15

And where to enter this line on a Asus Rt-n16?

If the router is still running the default firmware you probably can't set any dnsmasq options. Are you still on the default firmare, or did you flash your router with alternative firmware like DD-WRT?


#16

I will try again... does anyone know if i set this up, can my friend connect to my server if he puts my ip in his ATV ?


#17

I will try again... does anyone know if i set this up, can my friend connect to my server if he puts my ip in his ATV ?

No it will not.

It is possible to have remote access but it is not supported for a number of reasons, there are threads on it if you search this forum.

Wait for MyPlex support (if you had to ask the above question then i would not advise trying to hack it to work).


#18

No it will not.

It is possible to have remote access but it is not supported for a number of reasons, there are threads on it if you search this forum.

Wait for MyPlex support (if you had to ask the above question then i would not advise trying to hack it to work).

Could you help me abit in pointing out where to start to get this done ?

Because i want to set up a sever at my home so my friends can connect to that only chaging the dns setting in there ATV.


#19

Could you help me abit in pointing out where to start to get this done ?

Because i want to set up a sever at my home so my friends can connect to that only chaging the dns setting in there ATV.

Here's a topic on this subject with some ideas and problems people have or run into: http://forums.plexapp.com/index.php/topic/69871-will-this-work-outside-home-network/


#20

UPDATE:

I recopied, repasted the firewall entry and the problem is solved, weird.

I have this setup working, thx Wojo!

A question, I wonder if it is possible to allow other devices to connect to the real trailers.apple.com.

Now, other devices on the network go this message when trying to connect to that site.

I have address=/trailers.apple.com/

If I use address=/trailers.apple.com/ , trailers.apple.com open the router config

Here is the firewall entry

iptables -t nat -A PREROUTING -s 192.168.0.195 -d 192.168.2.1 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 192.168.0.111:8090

.195 = ATV

.1 = TOMATO

.111 = PlexConnect

Error response

Error code 403.

Message: Not Serving Client 192.168.0.111.

Error code explanation: 403 = Request forbidden -- authorization will not help.