Would like to show a message page to all wlan network users when there are adsl service issues.
Know how to divert the traffic to the httpd server using iptables, but how can one make the Busybox's http server
respond to any request, even if the destination header of the request is a site on the internet ?
Apache has the AliasMatch entry in the httpd.conf file for this. Can Busybox's server do this ???
Topic: how to divert all http traffic to OpenWRT's webserver
The content of this topic has been archived on 5 May 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.
Maybe you can try using a captive portal that should do the trick.
(Last edited by RItalMan on 23 Sep 2005, 16:33)
thanks; question is how to make OpenWRT's httpd server respond to any request, even if the request is originally not intended for the OpenWRT's server.
Have a script that tests availability of internet access via ADSL/WAN; if OK all http requests should go out onto the internet normally; if not OK would like the OpenWRT's server to respond with a page that I can define, even if the OpenWRT server is not at all the URL that the user has defined. But this requires that httpd translates whatever internet URL requested into the page defined by me in the WRT54G. How to do that ?
Here's how I would do it:
1. Every x seconds or minutes, run a script which checks for WAN access. You could do anything here, such as:
- Ping an Internet server
- Use "wget" to try and connect to a webserver on the Internet
- Check that the WAN IP address is valid
2. If the above script returns a negative response, add an IPTables entry to the firewall which does the following:
- Alters the PEROUTING table to change the destination IP address of any HTTP (Port 80) packets to be the router
- Alters the INPUT table to allow connections to the internal webserver
After that, any connections to anywhere on TCP Port 80 will be NAT translated and redirected to the router's webserver. Of course, in the meantime you keep your WAN checking script running at regular intervals. As soon as the WAN comes back up, your script removes the IPTables entries you made.
How does that sound?
Kaldek
> How does that sound?
That doesn't solve the problem. The problem is that either the web server needs to respond to any request, or a redirect needs to be done. I would suppose that the earlier suggestion to use a splash like nocatsplash would work - the script would just need to turn it on/off as needed.
- DL
Use a shell script via inetd (which you'll need to install), or some other method of having it listen on a tcp port - netcat maybe? : nc -l -p 81 -e <script>
Then have your iptables rule redirect clients to this script (which doesn't have to be on port 80), which will in turn redirect them to any other host/port of your choosing. it'll strip the url requested, so you'll need to have the info page you want to show at the root of the webserver you redirect to.
This is completely untested on openwrt, but I have made a couple of modifications for use on openwrt. I use it quite successfully on several *nix servers at work.
EDIT: I've just tested it, with netcat - works fine. (and just for the record, if you're redirecting to 80 somewhere, you can leave 'newport' empty)
#!/bin/sh
#
# Simple script to run out of (x)inetd to redirect the default http port
# 80 to another location
#
########################
# Config:
newhost=<name of host with info page>
newport=<port of webserver on host>
ssl=no
keepurl=no
########################
# No changes below here.
go=no
get=no
head=no
error=no
while read line;do
line=$(echo "$line" | tr -d '\n\r')
case "$line" in
GET*|HEAD*|get*|head*)
# The bit we really want..
type=$(echo "$line" | cut -d' ' -f1 | tr 'a-z' 'A-Z')
if [ "$keepurl" = "yes" ];then
requrl=$(echo "$line" | cut -d' ' -f2)
else
requrl="/"
fi
proto=$(echo "$line" | cut -d' ' -f3 | tr 'a-z' 'A-Z')
if [ "$(echo "$requrl" | cut -c1)" = "/" ];then
[ "$type" = "HEAD" ] && head=yes
if [ "$proto" = "HTTP/1.1" -o "$proto" = "HTTP/1.0" ];then
# Good protocol, do nothing
get=yes
elif [ "$proto" = "" ];then
# No proto, we can go ahead
if [ "$head" = "no" ]; then
go=yes
else
pagetext="Your browser sent a request that this server could not understand.<P>\r
client sent invalid HTTP/0.9 request: ${line}<P>"
error=yes
fi
else
# Error (bad proto)
pagetext="Your browser sent a request that this server could not understand.<P>\r
The request line contained invalid characters following the protocol string.<P>\r
<P>"
error=yes
fi
else
# Error (bad requested url)
pagetext="Your browser sent a request that this server could not un derstand.<P>\r
Invalid URI in request ${line}<P>"
error=yes
fi
;;
'')
# The 'do' line (empty line, or double CR)
if [ "$get" = "yes" ];then
go=yes
fi
;;
*)
# Just a random line from the HTTP protocol that we can ignore
;;
esac
if [ "$go" = "yes" -o "$error" = "yes" ];then
break
fi
done
if [ "$go" = "no" -a "$error" = "no" ];then
# We didn't get any double CR to go ahead
exit 0
fi
# Set some variables for the output
servername=$(nvram get wan_hostname)
if [ "$error" = "no" ];then
s=""
if [ "$ssl" = "yes" ]; then s="s" ;fi
if [ -n "$newport" ]; then newport=":${newport}";fi
newurl="http${s}://${newhost}${newport}${requrl}"
pagetext="The page you are after is <A HREF=\"${newurl}\">here</A>.<P>"
code="302"
title="Found"
else
code="400"
title="Bad Request"
fi
# Do the redirect:
if [ "$proto" != "" ];then
date=$(TZ=GMT date "+%a, %e %b %Y %T %Z")
echo -ne "HTTP/1.1 ${code} ${title}\r\n"
echo -ne "Date: ${date}\r\n"
echo -ne "Server: HTTP-Redirect.sh\r\n"
if [ "$error" = "no" ]; then
echo -ne "Location: ${newurl}\r\n"
fi
echo -ne "Connection: close\r\n"
echo -ne "Content-Type: text/html; charset=iso-8859-1\r\n"
echo -ne "\r\n"
[ "$head" = "yes" ] && exit 0
fi
echo -ne \
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r
<HTML><HEAD>\r
<TITLE>${code} ${title}</TITLE>\r
</HEAD><BODY>\r
<H1>${title}</H1>\r
${pagetext}\r
<HR>\r
<ADDRESS>HTTP Server at ${servername} Port 80</ADDRESS>\r
</BODY></HTML>\r"
exit 0(Last edited by mjb on 24 Sep 2005, 05:28)
thanks so much for all suggestions ! Will try them out this weekend and post results !
as promised the results of experiments to show a message page to all internal network users when adsl is not available:
A simple solution is one on basis of 'nc'. But nc terminates after it has been contacted one time. So it needs to be in a permanent loop that restarts nc whenever it has stopped. As I only want to show one particular html page when the adsl connectivity is not available, I used nc's option to receive input from a file, in this case a file in html format. So there is no need for the redirect script as kindly suggested by MJB if a text message is enough.
If a more sophisticated message is required with all html capabilities and graphics the script suggested by mjb will help out.
Had already a crond controlled script that tries the adsl connection every three minutes with three pings; if it fails I make sure via telnet that the modem is in working condition and now also call a script 'redirect_start'.
That script activates nc listening on port 81, it redirects via iptables all port 80 traffic to port 81 of the wrt54g, and it starts another script that pings every second to the provider to see whether the line is back up already. If it is back up from the pinging script a script 'redirect_stop' is called which removes the iptables entry and kills nc and the pinging script. Make sure that in the crond started script always redirect_stop precedes redirect_start to prevent accumulation of processes. After all it can happen that after three minutes the line did not come back up and this gets detected again. Here the simple scripts I am now using (v2.2 box, adsl is on vlan1):
***/etc/redirect_start***
#!/bin/sh
IFS=
/usr/sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to-destination **IP_of_WRT**:81
/usr/sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -i vlan0 -j DNAT --to-destination **IP_of_WRT**:81
/etc/spawn_nc
/etc/spawn_ping
***/etc/spawn_nc***
#!/bin/sh
IFS=
while :; do
/usr/bin/nc -l -p 81 < **/www/infopage.html** > /dev/null
done &
***/etc/spawn_ping***
#!/bin/sh
IFS=
while :; do
if /bin/ping -c 1 **ip_of_provider** | grep -q '1 packets received'; then
/etc/redirect_stop
else
/bin/sleep 1
fi
done &
***/etc/redirect_stop***
#!/bin/sh
IFS=
/usr/sbin/iptables -t nat -D PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to-destination **IP_of_WRT**:81
/usr/sbin/iptables -t nat -D PREROUTING -p tcp --dport 80 -i vlan0 -j DNAT --to-destination **IP_of_WRT**:81
/usr/bin/killall -9 spawn_nc
/usr/bin/killall -9 nc
/usr/bin/killall -9 spawn_ping
(Last edited by doddel on 27 Sep 2005, 10:06)
That's a nifty solution. With regards to nc terminating though, why don't you just use the xinetd superserver, which will handle binding it to port 81, and ensuring that any connections fire a new instance of nc?
Kaldek
why don't you just use the xinetd superserver, which will handle binding it to port 81, and ensuring that any connections fire a new instance of nc?
Or call the script/cat the file directly... (xinetd would replace nc)
But nc terminates after it has been contacted one time.
Ewps... sorry, forgot nc did that. I only suggested it because it's in the default RC3 install.
kaldek wrote:why don't you just use the xinetd superserver, which will handle binding it to port 81, and ensuring that any connections fire a new instance of nc?
Or call the script/cat the file directly... (xinetd would replace nc)
Ah yeah... DUH some days I'm so stupid.
Thanks for straightening me out.
Kaldek
Thanks for further suggestions.
Have installed xinetd, no problem, but have not found a way to then get cat or nc to give a reply to the calling browser. Used port 81 for test purpose and xinetd spawns the defined answering process but it seems that the answering process has no awareness of port 81 and just sends its output to standard output. Port 81 sort of triggers the start but then cat does not get connected to that port. NC, in turn, starts listening but the opening call was already used by xinetd and further nothing happens. Am probably missing something in the setup of xinetd and its service descriptor file for the answering or redirect script to work properly but don't know yet what it is.
In the mean time the other solution works but agree that xinetd would be the more elegant way to control responses to multiple browsers and their users in a concurrent way.
(Last edited by doddel on 28 Sep 2005, 10:33)
Used port 81 for test purpose and xinetd spawns the defined answering process but it seems that the answering process has no awareness of port 81 and just sends its output to standard output. Port 81 sort of triggers the start but then cat does not get connected to that port.
That's how xinetd is supposed to work. it listens on the port, and provides the glue between the stdout of a script/program and the network connection. nc and xinetd are mutually exclusive in this example.
The discussion might have continued from here.
