A SOCKS implementation for OCaml

I have been working on a SOCKS implementation for OCaml and specially for MirageOS. It’s not really complete or stable yet (not even published), it only has a couple of proof of concepts on the examples directory and it doesn’t integrate with the well known libraries of the ecosystem.

I would like to ask for feedback, and some thoughts about how could we have that in Conduit and Cohttp for example, so It’d be just plugged in into those libraries without having to directly depending on it. I plan to implement that for those libraries and have it submitted upstream, but not without some clear thoughts about how to make a clear interface for that.

Besides being sloppy, I have a few issues described on GitHub, and it should be addressed on the next few days. Anyone is welcome to discuss those issues as some of them are still foggy for me, and having some other views on that would be great.

8 Likes

Interesting – I found another (unreleased) SOCKS implementation at GitHub - cfcs/ocaml-socks: SOCKS4a and SOCKS5 (RFC 1928; RFC 1929) handling for ocaml clients and servers which may inspire you.

About MirageOS interfaces, I can see a difference in proxy (server) and client. A proxy may only provide the TCP listener and forward requests.

But a SOCKS client is more tricky, since the FLOW module type (GitHub - mirage/mirage-flow: Flow implementations for Mirage) does not define a “create_connection”. It may be useful to look into GitHub - dinosaure/paf-le-chien: Port of HTTP/AF with Mirage and Tuyau (Proof Of Concept) (used by e.g. ocaml-git in MirageOS to establish client connections). Since paf is extensible, this should fit pretty nicely into optional usage of SOCKS.

A similar library is happy eyeballs (GitHub - roburio/happy-eyeballs: An implementation of happy eyeballs (RFC 8305) in OCaml with lwt) - which API is to connect to a remote hostname (and port(s)), the result promise being an established connection (and the IP and port used) or an error.

3 Likes

But a SOCKS client is more tricky, since the FLOW module type (GitHub - mirage/mirage-flow: Flow implementations for Mirage) does not define a “create_connection”. It may be useful to look into GitHub - dinosaure/paf-le-chien: Port of HTTP/AF with Mirage and Tuyau (Proof Of Concept) (used by e.g. ocaml-git in MirageOS to establish client connections). Since paf is extensible, this should fit pretty nicely into optional usage of SOCKS.

A similar library is happy eyeballs (GitHub - roburio/happy-eyeballs: An implementation of happy eyeballs (RFC 8305) in OCaml with lwt ) - which API is to connect to a remote hostname (and port(s)), the result promise being an established connection (and the IP and port used) or an error.

I’m currently on that :slight_smile: !

Thank you! That’s a great one! I took a look on that, but decided to try to make something to work first so I could have a better understanding of the protocols separately, and that one has a lot of things together. I should definitely take a look now that I can understand how SOCKS4 works.

@dinosaure is doing a great work for the Mirage implementation, and that gave me a lot of ideas on how to improve the LWT Unix part.

I didn’t know httpaf was extensible (did I understand that correctly, though?), neither about happy eyeballs. I should probably make a better example for LWT Unix, but I am not being able to have a dependency on dune for the example project without messing with the whole project, it doesn’t build and I had to to “ignore” the dune file (renamed it to _dune).

Is it possible to dune to ignore some part of the project? Or should I add an socks-examples.opam file for those dependencies?

1 Like