I'm working on a project where I'd like to redirect all traffic from a domain name to a specific port at a specific IP address with the settings on my local machine. The hosts file almost does what I want, except for the port specific part.
For example, in the hosts file, I can type
"127.0.0.1 example.com"
and then when I type 'example.com' into my browser, it redirects to the server at localhost.
I'd like to be able to write
"127.0.0.1:123 example.com"
to have example.com redirect to port 123 on localhost.
Is there a good way to do this?
You can use an html redirect.
Replace ( ) with < >
(html)
(head)
(meta http-equiv="refresh" content="5;url=http://127.0.0.1:123")
(/head)
(/html)
That assumes that I have control of the remote machine. I need to do this redirection on the local end.
To give a bit more of a solid example of the problem:
Assume I control the server at MyDomain.com
Assume I do not control the server at example.com
I have an application which is hardcoded to send its data to example.com:80
I wish to have it send that data to MyDomain.com:123
Redirection on the remote machine is not a possibility.
I think I've got another way to do what I want (that doesn't rely upon redirection to another port), but I'd still like to know if anyone knows, is there a good way to do this?
(As an aside, if it were a situation where your solution was appropriate, why would you use an HTML redirect instead of using a .htaccess file or sending a redirect in the header data?)
Because, that assumes you're using Apache or an SSI/Scripting Language capable of sending headers.
You need a hex editor for the app, or possibly a proxy server if the app obeys proxy settings, or a really well crafted set of firewall rules.
Install the Squid web proxy on your system, and configure your browsers to use it. Squid has some powerful url pattern-matching and redirection facilities you could then use to redirect traffic however you like.
If you need this to happen *transparently* without having to configure your client programs to be aware of the proxy it's going to be difficult to do without setting up a seperate box between you and the internet. (Here's making the assumption your client is an OS X machine.) I was going to suggest using IPFW and NATD, but configuring it would be pretty tricky. Specifically, ipfw's "divert" function (required for natd) doesn't seem to be able to capture traffic initiated by your machine, only traffic routed through it. And there's also the problem of letting the squid process hit the internet on port 80 while diverting every other request. You *might* be able to get around that by adding an ip alias and binding squid to it. Maybe... yes, it does. Okay, do this: (Note this assumes you'll be able to assign *2* static IPs to your machine.)
1: Configure a static IP for your machine. Then open a terminal window and type "ifconfig". This will show you what device your ip lives on. I'm going to assume for the rest of this it's "en0". (Wired ethernet in most Macs.) I'm also going to pretend for the rest of this your ip address is "192.168.1.50". Substitute as appropriate.
2: At the terminal window, type this:
sudo ifconfig en0 alias 192.168.1.51/32
Substitute device name and IP as appropriate. Always make the netmask for aliases like this /32.
3: install Squid. For your test run we'll configure it so it just "works". You get to figure out your URL rewriting later. Refer to the copius amounts of documentation on the web for URL rewriting. Just to get running doing this to the default conf file should be sufficient:
# Look for "http_port" in the default config and make it this:
http_port 127.0.01:3128
# Right undernieth, add this oddball line:
tcp_outgoing_address 192.168.1.51
# Substitute the IP with your real alias, of course.
# Find the acl lines, and enable something like this over the "deny all"
acl our_networks src 192.168.1.50 127.0.0.1
http_access allow our_networks
Remember before starting squid to create the cache directory, chown it and the log directory to "nobody", and run "squid -z" to set up the cache hierachy. (you'll need to be root to do this. "sudo bash" will work to do this if you don't want to sudo before every command.)
4: Configure one browser to point at squid, and have another *not* use it. (Configure a proxy for FireFox while leaving Safari alone, for instance.) Verify squid works.
5: Run "sudo tcpdump -n -i en0 port 80" in your terminal window, and hit some websites with both browsers while watching it. You should see the requests from Safari coming from your "default" address, while the ones from Firefox through squid come from the second one.
6: download and compile "transproxy": http://transproxy.sourceforge.net/ Once installed, run it with a line like this:
./tproxy -s 8080 -r nobody 127.0.0.1 3128
(with a high port like 8080 you can run this as a mortal user)
7: Finally, set up these two firewall rules:
sudo ipfw add 90 allow tcp from 192.168.1.51 to any dst-port 80
sudo ipfw add 100 fwd 127.0.0.1,8080 tcp from any to any dst-port 80
The first line tells the firewall to let anything from squid go straight out, while the second tells it to throw any port 80 coming from the machine to transproxy. Which then throws it at squid.
You're done capturing. Verify with tcpdump that your web requests from safari are coming from squid now. You can also check if it's active by running the following command:
curl -I www.google.com
You'll see a "Via:" header indicating the request went through squid. Remove the second firewall rule:
sudo ipfw delete 100
And redirection will stop, and repeating the curl command *won't* show a header.
Now that it all works, set up squid to rewrite your URLs. Squid has some support internally (look at the dstdomain acl, for instance), but if your needs are complicated you might need a dedicated redirection plugin like "squirm". (google for it.)
Obviously you'll probably want to script setting this up and taking it down again if you do it on a regular basis.
If you can't set two static IPs you *might* be able to do this by setting tcp ToS (type of service) values in squid (see "tcp_outgoing_tos" in squid.conf) and setting up ipfw rules to redirect based on that rather then IP.
Have fun!
--Peace
Da*n my curiosity. That works too. So change the instructions above. Get rid of the static IP bits and setting an alias. Instead, make the following change to squid.conf:
# Change This:
# tcp_outgoing_address 192.168.1.51
# to
tcp_outgoing_tos 0x08
# And change your firewall rules to:
sudo ipfw add 90 allow ip from any to any iptos throughput
sudo ipfw add 100 fwd 127.0.0.1,8080 tcp from any to any dst-port 80
Now it should all work even with a dhcp IP.
Woot. And yeah, this is the sort of stuff I figure out for a living. *sigh*
--Peace
Axon, point taken.
Eudi, the assumption that it's an OS X client machine is correct. I'll spend the weekend playing with Squid, I think that configuration is just what I was looking for.