Almost Serving a Web Page with ION-DTN bpchat
This post is a follow up to Getting Started with ION-DTN 3.4.0 on FreeBSD. The follow up to this post is Serving a Web Page with ION-DTN bpsendfile and bprecvfile.
The goal is to serve a web page using an architecture like this.
In this post, a symbolic notation will be used to describe network connections at a single point in time. The software nodes in the above diagram will be represented by lowercase greek letters.
Notation | Meaning |
---|---|
α | client |
β | clientside reverse proxy |
γ | serverside forward proxy |
δ | server |
Unidirectional communication is represented by a pair of nodes. The first node is the source, the second node is the destination.
Notation | Meaning |
---|---|
αβ | client to reverse proxy connection |
βγ | reverse proxy to forward proxy connection |
γδ | forward proxy to server connection |
αδ | client-server request path |
δα | client-server response path |
Bidirectional communication is represented by a group of three nodes. Relevant communication starts at the first node, passes through or to the second node and ultimately comes back to the third node. The first and third letter are the same when describing normal bidirectional communication. They can differ when leaving off part of the path in one direction.
Notation | Meaning |
---|---|
αδα | client-server request-response path |
βγβ | proxy request-response path |
γδα | path from foward proxy to server and back to client |
Intermediate hops can be represented with a subscript. If the request and response take the same N hop path βγi and γβN-i are the same machine. The request and response need not take the same path. The number of hops need not be the same in both directions.
Notation | Meaning |
---|---|
βγ0 | zeroth hop from β to γ, i.e. β |
βγ1 | first hop from β to γ |
βγN | N-th hop from β to γ, i.e. γ for N hops |
γβ0 | zeroth hop from γ to β, i.e. γ |
γβN-1 | one hop from β coming from γ, for N hops |
γβN | at β coming from γ for N hops, N implies the same return path |
γβM-3 | three hops from β coming from γ, M implies a different return path |
Hardware and the application execution environment follow the same conventions, but use uppercase notation.
For example, Α is my MacBook, α is Safari, Δ is a virtual machine running on Α, and δ is a web server. ΑΒ1 is my wireless router and ΑΒ is simply a WiFi connection. ΒΑ1 and ΑΒ1 happen to be the same device. If αβ1 fails, my firewall is misconfigured. If ΑΒ1 fails, one of my kids pulled the plug on the router.
Where the OS and firmware fall is context specific. If building a router, a firmware bug would be an αβ1 failure. If simply using a router, a firmware bug is an ΑΒ1 failure.
Software Versions
Instructions
My unelaborate hardware setup is as follows. ΑΒ1 is a WiFi router.
For this exercise, host1.bprc will need to define two endpoints if everything is running on one machine. It may be useful to have a couple of extra endpoints for testing.
Make sure to (re)start ion.
Named terminals may make it easier to follow along. The following commands can be used to rename terminals.
δ Web Server
Set up a webserver that serves on 127.0.0.1:4000. If a web server is not handy, the following single file JSON/HTTP date server can be used. It is a crude implementation that is probably less robust than ideal.
date_server.sh
Run and test the server.
βγβ Communication Problems
The problem with something like HTTP is that αδ basically needs to be held open until α gets a response. The best case scenerio closes connections as the response travels back. The upshot is that βγβ needs to be an open connection over bp.
A fifo can not be used to hold an open connection with bpsendfile and bprecvfile.
bpchat can be used, by adding a mechanism to send EOF to γ when αβ is closed. The basic mechanism looks like this.
γ Forward Proxy
The goal is to build this forward proxy.
The serverside proxy communicates over bp/ltp with bpchat and connects to the webserver with nc. The proxy closes bp when eight EOT characters are found at the end of a line. This was chosen because I am fairly certain it is a unicode safe solution.
The forward proxy also changes the host and connection request headers so that the browser and web server will play better with the proxy setup. This fix is HTTP specific and can be removed for other protocols.
forward_proxy.sh
Create request.txt for testing. Note that a double newline is required at the end of this file.
Run and test the forward proxy. date_server.sh will probably send multiple responses. A real web server plays better with the proxy setup.
β Reverse Proxy
The reverse proxy described in this section crashes bp when the second request begins.
The reverse proxy is the last piece of the puzzle.
The reverse proxy is a mirror of the forward proxy. nc listens for connections and sends data through bpchat. The host is 0.0.0.0 because the reverse proxy serves the outside world. Note that the forward and reverse proxies need to use different ports if they are actually running on the same machine.
The reverse proxy does not need to modify the request or response stream. Modifications are handled by the forward proxy.
reverse_proxy.sh
Test from the terminal.
α Web Browser
Finally, test from a web browser. Hopefully everything works.
date_server.sh does not overload bp and plays well with a standard browser. It is more of a hack than a real web server so multiple responses are sent through the proxy layer. A web browser will ignore the extra data.
In theory using a proper web server should work better than date_server.sh. The HTML document is served without issue. Due to a bug in reverse_proxy.sh, the second request (a CSS file in my case) will cause bp to hang. This exercise has been posted as is because reproducable crashes are valuable.
References:
- ION, Bundle Protocol
- ION, ion-dtn-support Mailing List Archives
- ION, Getting Started with ION-DTN 3.4.0 on FreeBSD
- FreeBSD Handbook, Bridging
- FreeBSD Single Line Web Server With nc on FreeBSD
- UNIX, Netcat - network connections made easy
- UNIX, Using netcat to build a simple TCP proxy in Linux
- UNIX, Bourne Shell Scripting/Debugging and signal handling
- UNIX, Sh - the Bourne Shell
- UNIX, How can I trap interrupts in my shell script?
- UNIX, in bash does control-c = SIGINT or SIGTERM?
- UNIX, Sed and UTF-8 encoding
- UNIX, In Unix, how can I display the last lines of a file?
- UNIX, FIFO Operations
- UNIX, Trouble with piping through sed
- UNIX, how can I get sed to quit after the first matching address range?
- UNIX, Linux: Block until a string is matched in a file (“tail + grep with blocking”)
- UNIX, sed Find and Replace ASCII Control Codes / Nonprintable Characters
- UNIX, Can sed remove ‘double’ newline characters?
- UNIX, Case-insensitive search & replace with sed
- UNIX, How to replace whole line with sed?
- UNIX, change terminal title
- UNIX, ASCII Table and Description
- Networking, StackOverflow, what is the difference between proxy server and normal server?
- Networking, StackOverflow, Difference between proxy server and reverse proxy server
- Jekyll, Writing posts
- Jekyll, superscript in markdown (Github flavored)?
- Jekyll, Why there is no syntax for subscript and supscript?
- Wikipedia, UTF-8
- Wikipedia, Greek alphabet
- Wikipedia, End-of-Transmission character
- Wikipedia, Escape sequences in C