I developing a distributed reverse proxy called PortFusion. Its initial goal was to establish long-time, minimal-overhead, high-throughput TCP tunnels through firewalls especially for RDP -- few, long-lived connections.
Now though, to answer user demand for security and for helping activists, I am extending it to support encryption and supporting lots of short-lived connections.
Network:
Hu 1000 <============ Cx 1000 Au
[ 1001 1001=Ax:1000
^ |
| |
| |
| v
Cu 1001 Au Hx 1000
Squid <----- 1001=Au:3128 [ 1001 <----- Firefox
Legend:
u you
x person x
A address
H PortFusionHost
[ hosted service
C PortFusionClient
< establish bidirectional link
= encrypted, secure, bidirectional link
- localhost-only, normal, bidirectional link
Notes:
- Squid as a forward HTTP proxy
- Connection between two parties (===) are secure and encrypted
- Cu is in complete control of what services are shared with Hx
- A single Hu and a single Cu can handle multiple persons x y z
Questions:
In the network set-up above, I check the Connected
property of sockets, for example the one Hx
accepts from Firefox @Ax:1001
, to propagate closures to corresponding mirroring sockets used by Cu
to communicate with Squid.
But they always stay connected!!
- Why do Firefox sockets always stay connected?
- Is Firefox not responsible for closing the sockets it opens for HTTP requests once it has got responses?
- Are there other external triggers I am missing that I can sense and use for closing sockets?
Information Regarding Accepted Answer
Using the Connected
property of sockets was wrong. Following the tip in the accepted answer, I read this post and this MSDN article.
After the changes shown below, now both ends get immediately notified as soon as a request is fully responded to and closure propagation is working beautifully as expected. (In the past there was a different mechanism kicking in eventually clearing inactive sockets but it was not fast enough.)
Code (F#) Before:
try
request serverPort cl [||]
while transmitting && socket.Connected do
if socket.Available = 0
then Thread.Sleep Wait
else let length = read()
LogFlow "<:>" "Read" serverPort "<-" client length
request serverPort cl <| Array.sub buffer 0 length
with
Code After:
try
request serverPort cl [||]
while transmitting && read() > 0 do
let length = !lengthR
LogFlow "<:>" "Read" serverPort "<-" client length
request serverPort cl <| Array.sub buffer 0 length
with
where read
contains a call to Socket.Receive
and sets lengthR
.