At Flexiant, we had a need for a general websocket to tcp proxy. A cute apache module to do extensible web-sockets programming has been developed by self.disconnect, and is available on github here. I’ve hacked around with this to produce a generic, apache licensed, websocket proxy. A websocket connection is made over HTTP or HTTPS to apache, this calls the websocket module, which in turn calls my module, which makes an outbound tcp connection.

Some features:

  • It supports base64 and text format sockets. So it will thus process (for instance) VNC which works using base64 encoding.
  • Configuration is supplied through normal apache directory based configuration (see details below).
  • It’s extensible (currently by changing the code, rather than calling additional modules)

The configuration section looks like this, in this case set up to proxy VNC using a novnc client:

Note that the parameter you specify for Location must not be a file or directory that exists with your docroot, or you will just get 404 or similar. So, in the above example you must not have a file or directory at ${DOCROOT}/vncproxy.

I discovered that on a default apache install, you may also want to change the RequestReadTimeout, i.e.

I’m going to try and persuade self.disconnect to stick this in the examples directory for apache-websocket, but in the mean time the source is available here. Put it in the examples directory of apache-websocket, then compile, install and enable it with it with:
sudo apxs2 -c -i -a -I.. mod_websocket_tcp_proxy.c

[Update: see new blog post, git repo link here]

77 responses to “Using apache-websocket to proxy tcp connections”

  1. Hey, that’s really nice! I think it might be exactly what I searched for 🙂
    I want the websocket traffic to be redirected to a python script running on the same server. When I just change WebSocketTcpProxyHost to localhost and WebSocketTcpProxyPort to the port the script is running at, I get the 301 redirect, but the script gets no data at all. What am I doing wrong?
    Thanks!

  2. I would recommend you first try with the echo module from the examples directory in apache-websocket. I’d use the client.html which connects to the echo port as well as your test. When you have that working, switch to mine. Beyond that, if you switch LogLevel to debug, then your error log should tell you whether the module is being called at all, and where it is bailing out if it is. I’ve had problems when I’ve had my Location set to (e.g.) /test, but there is also a directory or file called test in /var/www; they sound a little like your problem.

  3. (it’s also possible that my code – shock horror – has a bug!)

  4. The websockets are working. At the moment I have an apache module which is called for websockets and just returns some dummy data. I’ll look into that a little more, perhaps I missed something ^^

  5. Well, after removing the file with the same name from /var/www the module gets called. I get “tcp_proxy_on_connect starting” but not “tcp_proxy_on_connect protocol correct”. Maybe you can help me on this one? 🙂

  6. What do you have ‘WebSocketTcpProxyProtocol’ set to, and what protocol name is your client using? From memory, you can miss that line out the config and it will accept any protocol.

  7. I removed WebSocketTcpProxyProtocol and WebSocketTcpProxyBase64, now it works. Thanks a lot!

  8. Glad you got it working.

    Removing WebSocketTcpProxyProtocol will make it accept any protocol; technically you should put in the correct protocol name.

    Removing WebSocketTcpProxyBase64 will make it use straight text encoding. Whilst the proxy module is 8-bit clean, my understanding is that the browser and/or the websockets library might not be (which is presumably the reason Base64 is used for protocols such as vnc/rfb over websockets). I suspect the specific problem may be handling of zero bytes.

  9. Has anyone tried this with Apache 2.4? I was able to compile and load mod_websocket_tcp_proxy just fine, but it doesn’t seem to be doing anything. I just get a 404. If I comment out “SetHandler websocket-handler”, it does list the contents of a directory that I created for debugging. Setting the Apache log level to Debug, doesn’t show anything at all for websockets.

  10. Zen: sorry, I’ve only tried it on apache-2.2. However, there is nothing that should break to my knowledge.

    Does apache-websocket itself work on 2.4? IE can you get the echo protocol and dumb-increment protocols to work?

    One idea: “it does list the contents of a directory that I created for debugging”. The location element MUST NOT overlap with an existing directory or file. I should make this a FAQ.

  11. Well, it’s interesting. I added this:

    And I get a 404. The log says:

    AH00128: File does not exist: /usr/local/apache2/htdocs/echo

  12. I’d try to get vanilla apache-websocket working first.

  13. Does anyone else experiences problems that the connections are not closed?
    Here is a debug output from the module, I added some lines in tcp_proxy_on_disconnect to see what is going on (especially I added debug output after line 434: apr_thread_join.. this one is never called!).

    [Wed Feb 29 14:08:23 2012] [debug] mod_websocket_tcp_proxy.c(301): tcp_proxy_on_connect starting
    [Wed Feb 29 14:08:23 2012] [debug] mod_websocket_tcp_proxy.c(336): tcp_proxy_on_connect protocol correct
    [Wed Feb 29 14:08:23 2012] [debug] mod_websocket_tcp_proxy.c(370): tcp_proxy_on_connect: base64 is 0
    [Wed Feb 29 14:08:23 2012] [debug] mod_websocket_tcp_proxy.c(109): tcp_proxy_do_tcp_connect: connect to host localhost port 6100
    [Wed Feb 29 14:08:23 2012] [debug] mod_websocket_tcp_proxy.c(165): tcp_proxy_run start
    [Wed Feb 29 14:08:24 2012] [debug] mod_websocket_tcp_proxy.c(423): tcp_proxy_on_disconnect
    [Wed Feb 29 14:08:24 2012] [debug] mod_websocket_tcp_proxy.c(433): tcp_proxy_on_disconnect: wait for thread

  14. Oh, I found this in dmesg:

    [7706451.741702] apache2[26750]: segfault at b75aa000 ip b75aa006 sp bfc57a9b error 7 in mod_websocket_tcp_proxy.so[b75aa000+3000]
    [7707226.770084] apache2[26971] general protection ip:b7427169 sp:bfa1940c error:0 in mod_websocket_tcp_proxy.so[b7425000+3000]

  15. Can you use any of the techniques here:
    http://httpd.apache.org/dev/debugging.html
    to trace that back to a line number?

    I’ve not seen anything like this before – OS, mpm version, apache version etc. would be useful.

  16. It seems the not closed connections and the crashing is unrelated. I have a lot more unclosed connections and only 1 or 2 crashes. I hopefully have enabled core dumping, so I might be able to get more details on the next crash. I run Apache 2.2.16 on Debian Squeeze.
    As for the unclosed connections: it seems the tcp_proxy_run function is captured in the recv loop eternally, if the TCP connection is closed (around line 176). The recv returns with a len of 0 and EOF. I fixed it by checking for tpd active in the loop conditions. It works for me, but don’t know if there are any side effects.

  17. Hi Alex,

    While adapting the handler to operate with a range of ports, I’ve discoverd a couple of bugs in the tcp_proxy_range_run function – (1) explains what Lennart is seeing with unclosed connections and (2) another relating to prematurely terminated connections when using the socket timeout.

    (1) the logic on the loop termination wasn’t quite right, so the thread never completed, leaving the connection wedged open:

    Replace:

    } while (!len && APR_STATUS_IS_EOF(rv));

    With:

    } while (!len && !APR_STATUS_IS_EOF(rv));

    (2) is a little more involved and requires some modifications to the if statements after the loop. I settled on this after giving up with trying to make APR return APR_TIMEUP as I expected (it was always returning APR_EOF for me):

    =%d, %s”,
    (unsigned long) len, rv, s);
    tcp_proxy_range_shutdown_socket(tpd);
    tpd->server->close(tpd->server);
    break;
    }
    else if ( len == 0 ) {
    /* nothing was read this time round. */
    continue;
    }

    I’ll be pushing these changes (and the handler I’ve been working on) to my fork of apache-websocket on github soon. I’ll post back once it’s available.

    Thanks for doing all the initial legwork that’s made this possible!

    Cheers,

    Mark.

  18. Alex Bligh Avatar
    Alex Bligh

    Mark,

    Yeah, that routine is problematic.

    I’ve actually rewritten all that stuff locally into a much simpler routine that looks for APR_TIMEUP and seems to work here. However, the purpose here was to proxy a particular kind of tcp session (vnc connections), and I’ve added some code which does DB lookups (optionally) and adds an (optional) custom handshake to the TCP session so it can cryptographically verify the websocket proxy is who it says it is. I suspect most of that isn’t terribly useful to others, and it would be better to modularise our specific bits, but I’m happy to pass you all of this.

    I’ve also got debian packaging if you are interested.

    Alex

  19. Ah, yes, I’d be very interested in seeing your latest iteration. I’ve just pushed my adapted code and a fix for that routine to your original to github (@mjtko) if you want to take a look – perhaps you could fork the repo and commit your latest bits and I can pull them across?

    Cheers,

    Mark.

  20. Heh, oddly enough, now I’ve reworked that function a couple of times, TIMEUP is now working for me. Must have been something odd to do with the usleep I removed for some reason. Confusing!

    Anyway, yes, regarding the latest bits and pieces, feel free to get in touch in whatever way you like. I’d very much like to see them/incorporate them into my fork of apache-websocket!

    Thanks again for sharing all your hard work!

    Cheers,

    Mark.

  21. Alex Bligh Avatar
    Alex Bligh

    Mark,

    Well, current code is at:
    http://blog.alex.org.uk/wp-uploads/extility-libapache2-mod-websocket.tar.gz

    Feel free to do your worst – apache licensed, but please do remove the name ‘extility’ from the package (trademark issues). What I did was fork my own code, and convert over to the version with vnc in it. You could mostly get back by search and replace. A credit for me and Flexiant remaining would be appreciated.

    Apologies for not giving you this in git format but it’s currently in work svn, which is not helpful, and I’ve no time to go fiddle with git now. Hopefully you can rip out (e.g.) the debian packaging pretty easily, and the vnc variant is a separate module. It will work for straight tcp sessions too if you don’t enable the various dubious options.

    The packaging needs build-depends to be set right.

    I don’t know your email address, but mine is alex (at) alex.org.uk

    Alex

  22. Thanks, I’ll take a look!

    No worries regarding git etc – I understand the barrier to entry with a new VCS is certainly not minimal (especially when it’s git! :-)). I would heartily recommend that when you do have time you give it a go though – I’ve certainly never looked back!

    I figured you’d have my email address as I have to leave it to leave a comment, but perhaps wordpress is hiding this from you. 🙂 I’ll send you a mail so we can continue discussions in a more suitable fashion than within a blog post comments stream!

    Cheers,

    Mark.

  23. Alex Bligh Avatar
    Alex Bligh

    Mark,

    I am a git user, it’s just that project went into work’s svn repo and has been ripped out the git repo and hence does not have the changesets. If I can get it upstream somewhere, I will happily lose the svn element!

    I do (or WordPress does) have your email address and I was being dumb.

    Alex

  24. Alex,

    I installed this module and updated the config, however when I try to restart apache2 I get this error. Any ideas?

    $ sudo service apache2 restart
    * Restarting web server apache2 * We failed to correctly shutdown apache, so we’re now killing all running apache processes. This is almost certainly suboptimal, so please make sure your system is working as you’d expect now!
    … waiting Syntax error on line 5 of /etc/apache2/mods-enabled/websocket_tcp_proxy.conf:
    Invalid command ‘WebSocketTcpProxyBase64’, perhaps misspelled or defined by a module not included in the server configuration

    -Brice

  25. Alex Bligh Avatar
    Alex Bligh

    Brice,

    Do the demo websocket applications (for instance the echo service) from self.disconnect’s github site work?

    Did you remember to enable the module?
    a2enmod websocket_tcp_proxy

    Sometimes ap2xs seems to disagree with Ubuntu’s/Debian’s apache module handling and doing an a2dismod and an a2enmod fixes it.

    Alex

  26. Alex,

    Thanks for the reply. I actually slightly disobeyed your instructions ( I did a sudo scons install instead of using apxs2 ). After running your command it installed correctly.

    I actually wrote something very close to this over the weekend mod_websocket_tcp ( I didn’t know about websocket_tcp_proxy ). It spawned a detached thread ( a TCP client ) which simply forwarded received JSON encoded messages from a TCP server to the websocket. I was able to get this working, but when I try to connect to yours I get a Unexpected response code: 404.

    I am running a TCP server on localhost:5900 ( from python ) and setup my config like this:

    Anything appear wrong to you?

    Brice

  27. Alex,

    I was using my old protocol in the JavaScript and was also pointing to my mongrel2 development server in the url’s port, I switched over to apache2 and changed the protocol to base64 and it works!

    This is awesome!

    Brice

  28. Brice,

    Glad it worked ok for you

    Alex

  29. Thanks again! I had a question (hope it’s quick).

    I’ve been able to use the general tcp function to do the vnc proxy as I’d hoped. I would like to be able to dynamically direct the destination host and port to different systems. I noted your vnc-specific module used a database backed index of hosts and ports based off of a key you pass in. I was wondering why you chose to do that rather than simply allowed the host/port parameters to be passed in by the client.

    Thanks again for sharing this!

    Tony

  30. Tony,

    If we allowed the end user to pass the VNC host/port parameters, they could connect to arbitrary ports on arbitrary servers. This would be undesirable (quite apart from using it to gain access to things of ours they shouldn’t, they could connect to anything on the internet using apache as a proxy). We also implement a layer of authentication depending on the host/port being connected to (or, more accurately, determine the host/port based on authentication credentials). I hope that helps.

    Alex

  31. That is what I suspected, but just wanted to confirm. Does your license declaration above include the mod_websocket_vnc_proxy.c file as well? I suspect we are going to use a modified version of your approach, but I’ll start clean if you prefer.

  32. Tony,

    Both mod_websocket_vnc_proxy.c and mod_websocket_tcp_proxy.c are published under the apache licence. You can do whatever you want with them that that licence permits. I would personally appreciate it if you published code changes, and contributed changes back (not that I have made that easy by not publishing it in a repo, but I believe Mark is fixing that), but that is certainly not a requirement.

    Alex

  33. Hi Alex,

    I’ve been trying your apache tcp websockets proxy for the last couple of days, and although initially it looked to be doing just as it says on the tin, I’ve noticed a couple of strange things when stress testing. I’m using self disconnect’s git commit 952e5b6 and mod_websocket_tcp_proxy.tar.gz from this page.

    Apache seems to not clean up after itself. I get to the point that there are about 250 children and then apache stops accepting websocket connections. The only solution is to restart apache.
    If the connection is closed at the proxy end, the connection in the web browser remains.
    I see random plain text http requests on SSL ports even though I’m not making them. I may be doing something stupid here though, as this is pretty bizarre.
    Apache, even though I had not used it for about 12 hours, spontaneously went into 100% usage, and I had to bounce it. Two apache children didn’t respond when apache bounced and had to be SIGKILLed. This may be related to my laptop having been suspended and resumed overnight before.
    Spurious disconnects.

    I’m starting to wonder whether using the apache/proxy approach is really suitable for a production environment where there may be some 100s of connections and also regular http/web traffic going on. The amount of apache children that were being spawned is a bit concerning. I might avoid apache altogether, but this means I have to take care of the HTTP overhead in my simple TCP server though, not to mention having to host it on another TCP port or IP address.

    I don’t know of any of the above have been solved in the various forks, it’s a bit hard to follow what the current status is.

    Regards,
    Will

  34. Will,

    In terms of code maturity, I’m happy to admit things are pretty early. The vnc proxy module I posted (which will also do raw tcp) has been cleaned up a bit, and we are using that in a production environment (albeit with a known version of apache with a fixed-ish config).

    Taking your points in order:

    if apache isn’t cleaning up after itself, that sounds like a problem with modwebsocket. Which mpm are you using? I have only tested on the prefork mpm rather than the threaded mpm, and there may be issues there (either with my code or more likely modwebsocket).
    this would might be the cause of (1). This definitely does not happen with the code I’m running at the moment (the vnc proxy code). I get an instant close. I do remember there were some issues with session clean up, and the vnc proxy code is neater in that respect.
    unless I have got the wrong end of the stick, the only ssl port should be the https:// web socket port. If that’s receiving plain text, then that’s a problem with your web socket client, not the proxy right at the other end of the system.
    again, I haven’t seen this.

    One issue I’ve had is that I have no line of communication to self.disconnect – my original plan was to put it in that git repo. Some time when I get some time, I’ll stick the whole lot up on github, if Mark T doesn’t beat me to it.

    Alex

  35. I have a question, i use websockify.exe where i can indicate what connections i want to proxy, for example, from x.x.x.x:yy to a.a.a.a:bb and if a want to proxy another connection a run another process with from and to parameters. My question is how to make this with this modulo, considering that IP from and TO can change when a new user wants to make a new remote desktop.

    thanks

    1. Alex Bligh Avatar
      Alex Bligh

      Are you trying to change the IP address of the remote desktop machine (i.e. a.a.a.a:bb) based on the source or destination address of the websocket session? IE is x.x.x.x:yy a source address, or a destination address? If it’s a destination address, just use a separate block for each, with the appropriate parameters in.

      If it’s a source address, well, that’s not a great idea as source addresses can be spoofed, but you could fix up the code to do that no doubt. What we do is interpret a key from the URL and look it up in a database.

  36. This is the thing. I have a server connected to a DataBase where it has all information about all computers on my LAN. The system is web-based, so when i enter and see the details of a specific computar, sometimes i want to make a remote connection to this machine. The Ip address i get it from de DB. Here is my problem, the source address could be anyone and destination address too. How could i tell to this modulo or how i have to use it to indicate the destination address. Remeber, that all computers has DHCP, so the ip es dinamically.

  37. Alex Bligh Avatar
    Alex Bligh

    Josue: as I said, we handle this by a parameter passed on the GET line of the websockets URL, which acts as a secret to index into a database. Provided you are connecting over SSL, that should be fine (guessing 256 bit numbers is hard). You will have to do a little coding to do the DB access bit (I used apache dbd functions) or wait until I get around to publishing our source – but it’s not difficult. The DB lookup then provides you with the parameters (e.g. outbound port and IP) to forward to. It’s completely dynamic.

  38. Mikael Kurula Avatar
    Mikael Kurula

    Hello!

    I have been struggling to install apache-websockets for a while, because I want to make a page running under node on port 8080 available through apache on port 80. The idea is to just point the browser to http://web.site/chat/ to reach the server on 8080. Is your plugin suitable for achieving this?

    Everything seemed to compile and install fine, but when I try to go to http://web.site/chat/ I only get a 404, although there is nothing called chat in the directory served by Apache. I get the following message in Apache’s error log:

    [Wed Jun 20 15:33:22 2012] [error] [client xxx] File does not exist: /var/www/html/chat

    My configuration in Apache is as follows:

    RequestReadTimeout body=300,minrate=1

    The modules are loaded by Apache; running apachectl -t -D DUMP_MODULES gives:
    websocket_module (shared)
    websocket_draft76_module (shared)
    websocket_tcp_proxy_module (shared)

    I have the same problem with disconnect’s echo example, and I have nowhere found any instructions on how to resolve this problem. Iasked for help on github, but got no response, so I now ask here. I also have the same problem in both Ubuntu and CentOS. I’ll be happy to provide more information if necessary.

    Very grateful for any help,
    Mikael

    1. Mikhail,

      Your problem is lack of understanding of how the websocket protocol works, I think. If you point your browser (i.e. the URL bar in your browser) to a URL which is a web socket URL, you will receive an error of some sort (a 404 sounds quite likely), because there is not a web page there to server. What there is at that URL is a web socket. The browser will not be negotiating the websocket handshake (i.e. ‘UPGRADE’ in the http session) in order to open the page. This is why if you look at self.disconnect’s websocket example programs (such as the echo client) you need to put in an .html file containing some Javascript at one location, which opens the web socket at another location. You then point your browser at the first location, which runs the JS, which in turn opens the web socket to the second location.

      I suggest you try to get self.disconnect’s examples working first (the echo example is the easiest).

      Once you have that running, it is relatively simple to make my proxy stuff run rather than the echo module.

      Alex

  39. Mikael Kurula Avatar
    Mikael Kurula

    I now see that the forum removed the IfModule etc. tags from the apache config, but they are persent in my config file.

  40. Mikael Kurula Avatar
    Mikael Kurula

    Thanks for your fast and helpful reply, Alex!

    Indeed, you’re right that I didn’t understand the websocket protocol works. Now I have some clue, but still not very deep understanding. Your advice helped me to understand that I should copy client.html and increment.html into e.g. the apache html root, and point my web browser to localhost/client.html. When I did that, both the echo and increment plugins worked fine.

    I also tried to install noVNC and run it as in the demo, but that failed for some reason, so I didn’t try to to proxy it via apache.

    Anyway, what I want to achieve is to serve this chat, which runs on node: https://github.com/jbenet/TeXchat via apache. Is your plugin what I’m looking for? Sorry for all these stupid questions, but I’m a mathematician and not a programmer. 🙂

  41. Mikael Kurula Avatar
    Mikael Kurula

    By the way, here is an example configuration for using texchat with nginx: https://github.com/jbenet/TeXchat/blob/master/backend/texchat.nginx.conf

    It seems to me that the essential thing is that the traffic to /chat and /socket.io is proxied throught to the node server running chat on port 8080. This is what I would like apache to do for me too.

  42. Mikael Kurula Avatar
    Mikael Kurula

    … and I also had this discussion with the developer of texchat, in case that helps: https://github.com/jbenet/TeXchat/issues/6#issuecomment-6379675

  43. Mikhael,

    You need my module if: (a) the protocol running between the browser client and the web server is WebSockets, AND (b) the protocol running inside that WebSocket session between the browser client and your chat server is a simple stream-like protocol that the chat server expects to be presented on a TCP socket.

    So, VNC runs over a TCP protocol (RFB on port 5900) but the browser can’t speak TCP itself, it has to encapsulate it in WebSockets. My module (plus self.disconnect’s stuff) strips of the WebSocket encapsulation, and passes it to the VNC server. If you are doing something comparable to that, then my module is what you need.

    I don’t know anything about your application, but a quick scan of the last comment suggested use of the ProxyPass directive in Apache. As ProxyPass is not compatible with WebSockets (in general), I am wondering whether your application uses WebSockets at all – perhaps it just posts JSON over HTTP or something?

  44. Hi,
    I am trying to compile mod_websocket_tcp_proxy.c on WindowsXP using SConstuct compiler, but it is throwing the following errors:

    mod_websocket_tcp_proxy.c(30) : error C2010: ‘.’ : unexpected in macro formal parameter list
    mod_websocket_tcp_proxy.c(81) : error C2275: ‘apr_size_t’ : illegal use of this type as an expression
    c:\program files\apache software foundation\apache2.2\include\apr.h(366) : see declaration of ‘apr_size_t’
    mod_websocket_tcp_proxy.c(81) : error C2146: syntax error : missing ‘;’ before identifier ‘len’
    mod_websocket_tcp_proxy.c(81) : error C2065: ‘len’ : undeclared identifier
    mod_websocket_tcp_proxy.c(82) : error C2065: ‘len’ : undeclared identifier
    mod_websocket_tcp_proxy.c(111) : error C2143: syntax error : missing ‘;’ before ‘type’
    mod_websocket_tcp_proxy.c(112) : error C2065: ‘port’ : undeclared identifier
    mod_websocket_tcp_proxy.c(117) : error C2065: ‘port’ : undeclared identifier
    mod_websocket_tcp_proxy.c(179) : warning C4013: ‘usleep’ undefined; assuming extern returning int
    mod_websocket_tcp_proxy.c(193) : error C2275: ‘size_t’ : illegal use of this type as an expression
    c:\program files\microsoft visual studio 9.0\vc\include\codeanalysis\sourceannotations.h(19) : see declaration of ‘size_t’
    mod_websocket_tcp_proxy.c(193) : error C2146: syntax error : missing ‘;’ before identifier ‘towrite’
    mod_websocket_tcp_proxy.c(193) : error C2065: ‘towrite’ : undeclared identifier
    mod_websocket_tcp_proxy.c(195) : error C2143: syntax error : missing ‘;’ before ‘type’
    mod_websocket_tcp_proxy.c(199) : error C2065: ‘towrite’ : undeclared identifier
    mod_websocket_tcp_proxy.c(199) : error C2065: ‘towrite’ : undeclared identifier
    mod_websocket_tcp_proxy.c(200) : error C2065: ‘wbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(200) : warning C4047: ‘=’ : ‘int’ differs in levels of indirection from ‘char *’
    mod_websocket_tcp_proxy.c(203) : error C2275: ‘size_t’ : illegal use of this type as an expression
    c:\program files\microsoft visual studio 9.0\vc\include\codeanalysis\sourceannotations.h(19) : see declaration of ‘size_t’
    mod_websocket_tcp_proxy.c(203) : error C2146: syntax error : missing ‘;’ before identifier ‘written’
    mod_websocket_tcp_proxy.c(203) : error C2065: ‘written’ : undeclared identifier
    mod_websocket_tcp_proxy.c(205) : error C2065: ‘wbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(205) : error C2065: ‘towrite’ : undeclared identifier
    mod_websocket_tcp_proxy.c(206) : error C2065: ‘written’ : undeclared identifier
    mod_websocket_tcp_proxy.c(206) : error C2065: ‘towrite’ : undeclared identifier
    mod_websocket_tcp_proxy.c(209) : error C2065: ‘written’ : undeclared identifier
    mod_websocket_tcp_proxy.c(244) : error C2143: syntax error : missing ‘;’ before ‘type’
    mod_websocket_tcp_proxy.c(245) : error C2065: ‘ztbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(249) : error C2065: ‘ztbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(249) : warning C4022: ‘free’ : pointer mismatch for actual parameter 1
    mod_websocket_tcp_proxy.c(252) : error C2065: ‘ztbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(252) : warning C4022: ‘memcpy’ : pointer mismatch for actual parameter 1
    mod_websocket_tcp_proxy.c(253) : error C2065: ‘ztbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(253) : warning C4047: ‘function’ : ‘const char *’ differs in levels of indirection from ‘int’
    mod_websocket_tcp_proxy.c(253) : warning C4024: ‘apr_base64_decode_binary’ : different types for formal and actual parameter 2
    mod_websocket_tcp_proxy.c(254) : error C2065: ‘ztbuf’ : undeclared identifier
    mod_websocket_tcp_proxy.c(254) : warning C4022: ‘free’ : pointer mismatch for actual parameter 1
    mod_websocket_tcp_proxy.c(355) : error C2275: ‘websocket_tcp_proxy_config_rec’ : illegal use of this type as an expression
    mod_websocket_tcp_proxy.c(42) : see declaration of ‘websocket_tcp_proxy_config_rec’
    scons: building terminated because of errors.

    Could you please tell me how to build this file.

    1. Alex Bligh Avatar
      Alex Bligh

      The code is not tested on Windows – only on UNIX. I have no Windows development environment. I suspect fixing it would be pretty simple. Patches accepted.

  45. Can I get compiled binary of mod_websocket_tcp_proxy.c file.

    1. Alex Bligh Avatar
      Alex Bligh

      That would rather depend on what operating system & compile settings you want.

  46. apr_socket_recv(tpd->tcpsocket, buf, &len); in tcp_proxy_run() is failing with the reason “An established connection was aborted by the software in your host machine.”

    Could you please tell me the possible reasons.

    1. Alex Bligh Avatar
      Alex Bligh

      I would guess that either whatever you are connecting to has closed the connection, or the connection never established (firewall, wrong connection parameters etc.). Have a look with wireshark/tcpdump.

  47. Have you considered doing a fork/pull request to add your example?

    1. Alex Bligh Avatar
      Alex Bligh

      Yes, that would be good idea. I really need to move my code base to git (this was done for a work project, and, at least today, we use svn internally). I plan to do this at the same time as updating the patch slightly.

  48. Leonardo Moreno Avatar
    Leonardo Moreno

    Hi. I’m really happy to find this article because I need to deploy a web application that uses websockets and found that Apache doesn’t work nice with them.

    My problem right now is that I don’t know where to start. Can you tell me if there is some docs that can guide me with the installation?. I have my application deployed in tomcat behind Apache acting as a proxy and, until now, I haven’t been able to connect my client.

    I think is worth telling that I don’t have too much experience in compiling and installing Apache modules.

    Thanks in advance for any help.

    Regards

    1. Alex Bligh Avatar
      Alex Bligh

      I would start by getting self.disconnect’s apache module compiled and installed, and running the tests there. His documentation is better than mine currently (which isn’t saying much). You can then test the ‘echo’ service with a browser, and check all that works. Once you are happy that works, I’d compile mine (the same way) and try to slot that in. I’ve adapted his echo example before and made it connect to my module, and made it forward to port 25 (SMTP) and checked it produced the expected SMTP connect banner. Sorry not to have better documentation.

  49. Leonardo Moreno Avatar
    Leonardo Moreno

    Thanks for answering.

    I already installed self.disconnect module and test the examples. Both worked as expected, with the only problem that the connection is closed if no message is sent in a while (do you have idea why?).

    I already installed your module, but I don’t know how to configure it to connect to my endpoint. I need that when apache receive the ws connection attempt at ws://domain.com/ws/endpoint/ “redirects it” to localhost:8080/ws/endpoint/. Is this possible with your module?

    Last question. Wich version of your module should I use? the file linked in your post or the one linked in a comment response?

    I perfectly understand the lack of time and I usually don’t like to bother anybody with my problems, but I’m really needing this and after three days of research, this is the closest I’m been to resolve this problem.

  50. Alex Bligh Avatar
    Alex Bligh

    Leonardo,

    I’m guessing the connection is closed because of some form of timeout. There is an apache idle timeout which might cause the issue. We found one of these (I’m afraid I can’t remember which) enabled in Ubuntu’s stock apache (for instance).

    Re config, I’m not quite clear what you are trying to do here. My module will send an unwebsockified tcp stream to a local port. It sounds like what you want to do is proxy the websocket in its entirety, i.e. not decode the websockets protocol at all. If your Java program was listening on a local port with a normal Java socket, you could use my code. However, if your Java program wants a websocket communication, then you don’t want my code. You want something like mod_proxy as a reverse proxy. As you may know, due to the ‘unique way websockets is implemenented’ (contrary to the HTTP RFCs) you may have difficulty with mod_proxy. However, when I last looked you could make mod_proxy work (just) as a reverse proxy given the right settings. I’ve never tried this, and the information comes from Google and my memory.

    Re versions, either should work.

    Alex

Leave a Reply

Discover more from Alex Bligh's blog

Subscribe now to keep reading and get access to the full archive.

Continue reading