Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding on a port with netpipes/netcat

I am trying to write a simple bash script that is listening on a port and responding with a trivial HTTP response. My specific issue is that I am not sure if the port is available and in case of bind failure I fall back to next port until bind succeeds.

So far to me the easiest way to achieve this was something like:

for (( i=$PORT_BASE; i < $(($PORT_BASE+$PORT_RANGE)); i++ ))
do
  if [ $DEBUG -eq 1 ] ; then
    echo trying to bind on $i
  fi
  /usr/bin/faucet $i --out --daemon echo test 2>/dev/null
  if [ $? -eq 0 ] ; then                        #success?
    port=$i
    if [ $DEBUG -eq 1 ] ; then
      echo "bound on port $port"
    fi
    break
  fi
done

Here I am using faucet from netpipes Ubuntu package.

The problem with this is that if I simply print "test" to the output, curl complains about non-standard HTTP response (error code 18). That's fair enough as I don't print HTTP-compatible response.

If I replace echo test with echo -ne "HTTP/1.0 200 OK\r\n\r\ntest", curl still complains:

user@server:$ faucet 10020 --out --daemon echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"
...
user@client:$ curl ip.of.the.server:10020
curl: (56) Failure when receiving data from the peer

I think the problem lies in how faucet is printing the response and handling the connection. For example if I do the server side in netcat, curl works fine:

user@server:$ echo -ne "HTTP/1.0 200 OK\r\n\r\ntest\r\n" | nc -l 10020
...
user@client:$ curl ip.of.the.server:10020
test
user@client:$

I would be more than happy to replace faucet with netcat in my main script, but the problem is that I want to spawn independent server process to be able to run client from the same base shell. faucet has a very handy --daemon parameter as it forks to background and I can use $? (exit status code) to check if bind succeeded. If I was to use netcat for a similar purpose, I would have to fork it using & and $? would not work.

Does anybody know why faucet isn't responding correctly in this particular case and/or can suggest a solution to this problem. I am not married neither to faucet nor netcat but would like the solution to be implemented using bash or it's utilities (as opposed to write something in yet another scripting language, such as Perl or Python).

like image 888
mindas Avatar asked Dec 01 '25 08:12

mindas


1 Answers

faucet 10020 --out --daemon \
    echo -ne "HTTP/1.0 200 OK\r\nContent-Length: 4\r\n\r\ntest"

works fine. The issue seems to be that echo doesn't know how to properly shutdown a socket, using just close instead, and curl is unhappy about getting a -1 (disorderly shutdown) rather than a 0 (orderly shutdown) from recvfrom.

Try socat which sticks around to clean up after the child is done.

socat tcp-l:10020,fork,reuseaddr \
    exec:'echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"'
like image 171
ephemient Avatar answered Dec 03 '25 22:12

ephemient



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!