Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Or, "My home webserver thought it was ugly until it looked in the mirror."

Over a year ago, I had a situation where I wanted to see what my locally-served website looked like from the "outside." This was in a drive to configure my home network and webserver to correctly serve pages to anyone I send my IP address, what with all the various configuration issues facing me at the time. My home network consists of an internal LAN fed by a Linksys cable-modem router with ports 80 and 8080 forwarded to my local webserver.

"But," you say, "why don't you just use the local internal IP of your webserver to see your site?"

"Well," I reply, "I want to make sure people on the outside are getting the same thing I'm getting from the inside with no surprises. Also, from the inside, if I use my router's external IP to view my site, I get the 401/403 login challenge on my router's web administration panel."

"Hrumph."

Hrumph indeed. So, everyone with me: "Perl to the rescue!"

Problem analysis:


What I needed was a script that resided on my externally-hosted and paid-for domain host that I could use to reflect an HTTP request. I thought of methods to make it call only my home's IP (all of them smelly, mangled, and snarled), but I settled on making it general enough to be used from any system that had a running webserver. Hey, what a neat idea!

Wanna try? If you have an externally-accessible server that answers to port 8080 on your externally-visible IP address (I had to cludge to circumvent my provider's "port 80 filter"...) then take a look at your site here. You will, in theory, get your locally-hosted site as seen from my hosted site. (Actual mileage may vary. Expect requests from phaysis.com in your access logs.)

Configuration:


On my hosted site, I have a subdirectory set aside in my document root which contains the mirror.cgi script and an .htaccess config file (your host must allow .htaccess files for this to work).

Further documentation assumes your mirror subdirectory is called /mirror .

.htaccess:


The .htaccess file contents are as follows:
DirectoryIndex mirror.cgi ErrorDocument 404 /mirror/mirror.cgi

This tells Apache to serve mirror.cgi by default, which then executes to grab the root page on your local site. For any file on your local site which (surprise surprise) doesn't exist in the remote /mirror directory, Apache's ErrorDocument functions call your script to take care of file fetching.

mirror.cgi:


Ok, so here's the meat and potatos of our operation. What we're doing is creating a LWP::UserAgent instance to get files from the IP of the computer making the request. Currently, the code kind of looks inelegant (my apologies) but it has worked very well for me in its 1 1/2 years of existence (further proving Aristotle's suggestion that "Makeshifts last the longest").

The code for mirror.cgi is as follows:

#!/usr/bin/perl # mirror.cgi # gets the ip of the calling client, and sends an http request # to that client. This is used to browse the client's local web # server while getting around the client's router, in effect # showing the client how their locally-served site functions # from the outside. # Does not support sending post variables, yet. use LWP::UserAgent; ########## Handle the request and build a reflection request: ##### Get the client address $clientip = $ENV{'REMOTE_ADDR'}; ##### Get the requested URL $req_url = ($ENV{'REDIRECT_URL'}) ? $ENV{'REDIRECT_URL'} : ''; ##### Get rid of the leading directory on the local call $req_url =~ s/^\/mirror//gi; ##### Default to 8080, to bypass ISP's 80-filter $serverport = ":8080"; ##### Build the final URI/URL $geturl = "http://".$clientip.$serverport.$req_url; ########## Create a new user agent $ua = LWP::UserAgent->new( env_proxy => 1, keep_alive => 1, timeout => 30 ); ########## Create a new request $request = HTTP::Request->new('GET', $geturl); ########## Get the requested page with the new user agent $resultref = $ua->request($request); ########## Print the results ##### Print the returned headers print $resultref->{'_headers'}->as_string(); ##### Print blank line to end headers and begin document entity print "\n"; ##### And here's the body print $resultref->content; ########## exit; ##########

Hopefully, the code is simple and straightforward enough to warrant not much further explanation. It's a "straight wire" of a script, but it's just as effective. One caveat, though: this script doesn't handle POSTed form variables, only HTTP GET requests. I've considered extending to cover this, but currently there's little need.

Problem solved:


So, now all I have to do to see my internal site as though I was outside is to, in my example, request the page http://www.phaysis.com/mirror/, and voila, my server's hard drive comes to life as it serves a page request for my root index file. As a bonus, and much to my amazement, the script even handles images with no problems thanks to the flexibility of LWP's methods.

I hope this is of use to some of you. It certainly has been useful to me in testing scripting and design of my local site (which is quicker and easier to update than my hosted space), as well as testing external access issues such as ISP's that filter what their paying customers can do, router port-forwarding issues, and local LAN connectivity issues. Very useful.

Heh, and just remember to ignore all the "404 /mirror/..." messages in your hosted domain's error_log files. Those'll get you.

ENJOY!

-Shawn / (Ph) Phaysis
If idle hands are the tools of the devil, are idol tools the hands of god?
update: fixed some typos and some formatting issues - Phaysis


In reply to Viewing locally-served pages from the outside, while *inside*! by Phaysis

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2024-03-28 17:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found