0

I'm trying to use httptunnel for tunnel a connection like this:
on Server:

sudo hts -F localhost:10000 81
nc -l -p 10000

On Client:

sudo htc -F 7777 server_ip_address:81
telnet 127.0.0.1 7777

but telnet fails:

Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.

syslog says:

Nov  6 01:41:37 r1y4n-PC htc[1695]: htc (httptunnel) 3.3 started with arguments:
Nov  6 01:41:37 r1y4n-PC htc[1695]:   me = htc
Nov  6 01:41:37 r1y4n-PC htc[1695]:   device = (null)
Nov  6 01:41:37 r1y4n-PC htc[1695]:   host_name = server_ip_address
Nov  6 01:41:37 r1y4n-PC htc[1695]:   host_port = 81
Nov  6 01:41:37 r1y4n-PC htc[1695]:   proxy_name = (null)
Nov  6 01:41:37 r1y4n-PC htc[1695]:   proxy_port = 8080
Nov  6 01:41:37 r1y4n-PC htc[1695]:   proxy_buffer_size = 0
Nov  6 01:41:37 r1y4n-PC htc[1695]:   proxy_buffer_timeout = -1
Nov  6 01:41:37 r1y4n-PC htc[1695]:   content_length = 102400
Nov  6 01:41:37 r1y4n-PC htc[1695]:   forward_port = 7777
Nov  6 01:41:37 r1y4n-PC htc[1695]:   max_connection_age = 300
Nov  6 01:41:37 r1y4n-PC htc[1695]:   use_std = 0
Nov  6 01:41:37 r1y4n-PC htc[1695]:   strict_content_length = 0
Nov  6 01:41:37 r1y4n-PC htc[1695]:   keep_alive = 5
Nov  6 01:41:37 r1y4n-PC htc[1695]:   proxy_authorization = (null)
Nov  6 01:41:37 r1y4n-PC htc[1695]:   user_agent = (null)
Nov  6 01:41:37 r1y4n-PC htc[1695]:   debug_level = 0
Nov  6 01:41:49 r1y4n-PC htc[1695]: http_write_request: write error: Invalid argument
Nov  6 01:41:49 r1y4n-PC htc[1695]: couldn't open tunnel: Invalid argument
Nov  6 01:41:49 r1y4n-PC htc[1695]: exit with status = 1

What causes the http_write_request: write error: Invalid argument ?
How can I tunnel my connection correctly?
Both server and client are Ubuntu 14.04

Thanks

1

How can I tunnel my connection correctly?

Fix httptunnel. See below.

Note that you are using nc with erroneous arguments, but it still seems to work. From man nc:

-l        Used to specify that nc should listen for an incoming connection rather than initiate a connection to a remote host. It is an error to use this option in conjunction with the -p, -s, or -z options.


What causes the http_write_request: write error: Invalid argument?

Invalid argument is a stringified version of POSIX error code EINVAL.

The error code was returned from the write libc function/kernel syscall which was indirectly called by the http_write_request function of httptunnel client. EINVAL means:

fd is attached to an object which is unsuitable for writing; or the file was opened with the O_DIRECT flag, and either the address specified in buf, the value specified in count, or the current file offset is not suitably aligned.

Before write() is called, the socket is configured with various options using the setsockopt libc function / kernel syscall. One of these options is SO_SNDLOWAT. You can read about what that is supposed to do here. Note that:

SO_SNDLOWAT is not changeable on Linux (setsockopt(2) fails with the error ENOPROTOOPT)

so it's a useless call to make on linux in the first place, at least as of 2015.

After running htc with strace, I noticed an inconsistency between the code and the syscall arguments reported by strace. The code in the tunnel_out_setsockopts function is trying to set the SO_SNDLOWAT option, but strace reports setsockopt(5, SOL_TCP, TCP_REPAIR, [1], 4) = 0. Take a closer look at the socket man page where SO_SNDLOWAT is listed as an option, and note the following:

The socket options listed below can be set by using setsockopt(2) and read with getsockopt(2) with the socket level set to SOL_SOCKET for all sockets.

tunnel_out_setsockopts does not use SOL_SOCKET for the SO_SNDLOWAT option; it uses the result of another function (get_proto_number) instead. This is a bug. This may be due to an inconsistency with prior versions of the kernel or libc API, but I suspect that is unlikely.

Unfortunately, fixing this bug by replacing the socket level argument with SOL_SOCKET does not result in a usable tunnel. The write call which was previously failing now succeeds, but the program fails about a second later with ETIMEDOUT on a read call.

There is another function tunnel_in_setsockopts which attempts to set SO_RCVLOWAT with the output of get_proto_numer instead of SOL_SOCKET. This is another bug.

Fixing these two causes the tunnel to work properly.

Server
nc -l 10000
sudo hts -F localhost:10000 81

Client
htc -F 7777 localhost:81
telnet localhost 7777

This bug was already reported against Ubuntu 14.04 here. I suggest you mark it as affecting you. I have uploaded a patch as a fix for the problem, but it will still need to be accepted by Ubuntu.

2
  • Thanks, yes this fixed the problem, both by applying your patch or fetching a latest source of httptunnel (the patch is applied there); Thanks
    – Ariyan
    Nov 6 '15 at 12:59
  • 1
    Wow. Based on my past experience with Ubuntu bug reports, I was extremely surprised when I (mis)understood what you said to mean that it took less than 10 hours for Ubuntu to push an updated package. What actually happened is that it was fixed upstream before Ubuntu even noticed the update to 1443660. Just as good! Now Ubuntu might just rebase.
    – tweej
    Nov 6 '15 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.