Settings

Theme

Show HN: Encrypted VPN in 2k lines of Go

github.com

123 points by twitchyliquid64 8 years ago · 65 comments

Reader

arianvanp 8 years ago

Related: Wireguard is a new VPN for linux in 4k lines of C https://www.wireguard.com/

the model of wireguard has been proven correct by formal methods. Builds on modern crypto, and they kept code short for auditing purposes.

  • jorrizza 8 years ago

    There's also a work-in-progress Go implementation of Wireguard, found over here: https://git.zx2c4.com/wireguard-go/about/

  • twitchyliquid64OP 8 years ago

    My concern is that 'built on modern crypto' and 'reviewed by cryptographers' amounts to 'rolled our own crypto'. IMHO history has shown us time and time again that this is a bad idea - we should use the protocols and ciphers that have stood the test of time. Building subnet using TLS was an architectural choice to avoid playing the role of cryptographer and inevitably getting it wrong.

    • zx2c4 8 years ago

      What a bunch of senseless FUD.

      WireGuard is based on the Noise Protocol Framework [1], designed by the same fella as the Signal Protocol, and already used in production by millions of devices all around the world inside of WhatsApp. Not only that, but we have a formal verification [2] that the crypto is correct in the symbolic model. The WireGuard paper itself [3] was presented to the academic community at NDSS [4]. It's most certainly not the hastily-made nonsense you imply it is with the phrase "rolled our own crypto".

      Meanwhile your project, "subnet", tunnels TCP over TCP, which is well known for having pathologically bad performance characteristics [5]. It also has no binding between certificates and the IP addresses that a certificate is allowed to be inside the tunnel, and, unless I've misread, it allows different peers to hijack each others' IP addresses simply by asking [6].

      There's a lot of work that goes into doing tunneling well. I encourage your effort to make a fun toy project; it's a great learning opportunity. But please don't spread FUD about other projects without first understanding them.

      [1] https://noiseprotocol.org

      [2] https://www.wireguard.com/formal-verification/

      [3] https://www.wireguard.com/papers/wireguard.pdf

      [4] https://www.ndss-symposium.org/ndss2017/

      [5] https://www.google.com/search?q=tcp+over+tcp

      [6] https://github.com/twitchyliquid64/subnet/blob/50fc8fe2b6ccf...

      • twitchyliquid64OP 8 years ago

        > What a bunch of senseless FUD.

        inb4 strawman arguments and other funzies.

        Perhaps you should argue with me on my actual assertion, which is that 'we should use crypto that has stood the test and scrutiny of time'. Do not interpret my criticism as a personal attack.

        > already used in production by millions of devices all around the world inside of WhatsApp.

        Cool. This is good because that means we have a lot of eyes looking at it.

        > formal verification that the crypto is correct in the symbolic model.

        This is great and we need more of this kind of work. I don't think its good enough however; most practical attacks rely on side channels, implementation mistakes (formal verification helps in catching these but don't get you all the way), and other obscurities. I stand by my assertion that we should use crypto that has stood the test of time.

        > The WireGuard paper itself [3] was presented to the academic community at NDSS

        Congrats I guess? relevance?

        > not the hastily-made nonsense you imply it is with the phrase "rolled our own crypto"

        I made no such implication. 'Roll your own crypto' is a common phrase (at least in my circles) meaning to do it yourself instead of depend on someone else's implementation. Again, I don't see what this has to do with my assertion to use old and battle tested crypto.

        > "subnet", tunnels TCP over TCP, which is well known for having pathologically bad performance characteristics

        Correct, have a gold star. What does this have to do with crypto?

        As you could tell if you scrolled down and read the other discussions around TCP-in-TCP, I am fully aware of the implication of my design decision, and stand by it is the right balance of simplicity, security, and speed (well, thats relative, but for what I was intending it for).

        > It also has no binding between certificates and the IP addresses that a certificate is allowed to be inside the tunnel, and, unless I've misread, it allows different peers to hijack each others' IP addresses simply by asking

        Correct, I am making the assumption that if posess a private key and cert minted by the server you are trusted. This could be fixed at the cost of additional complexity, loosing the ability for a client to change his address, and less alcohol-time on the developers part. That said, if someone asked me to network together hostile entities, I would have given him some coolaid instead of Go code. But I'm digressing, lets get back on topic.

        > But please don't spread FUD about other projects without first understanding them.

        I have done no such thing. I stand by my assertion that we should use Crypto that has stood the test of time. Am I not allowed to raise such assertions and discuss them on merit?

        • freedomben 8 years ago

          Bonus points for being classy despite being attacked.

          > What a bunch of senseless FUD

          Is not a very courteous way to begin a rebuttal. Definitely makes it feel like an ad hominem.

    • daxorid 8 years ago

      It builds on Noise, which is very highly regarded and reasonably well researched in crypto circles. Ironically (vis-a-vis your comment), it was designed largely to avoid the mistakes inherent in developers "rolling [their] own" crypto on TLS with poorly chosen stacks, ciphers, parameters, downgrade criteria, etc.

      https://noiseprotocol.org/noise.html

      • twitchyliquid64OP 8 years ago

        Guess you could say noise is pretty quiet xD

        +1 for trying to eliminate complexity from developer error. This was one of the worst cows in the herd for OpenSSL.

        That said, I think a bit of good design on the APIs part can go a long way. For Instance, I think Go's crypto/tls aint bad: Its pretty difficult to 'accidentally' configure it in a shocking configuration (suites have to be overridden, turning off verification requires you to set a field called InsecureNoVerify etc).

sethammons 8 years ago

The project structure is fighting againts norms. The author should not have src checked in. They should have their package as the root so it is "go get-able" and does not require the user to alter their GOPATH. To ensure that the proper dependency versions are present, they should vendor the dependencies. I would have opened an issue on GitHub for them, but I am not signed in currently. Cheers on releasing a neat tool.

EDIT: got off my mobile and to a laptop and submitted https://github.com/twitchyliquid64/subnet/issues/3.

sAbakumoff 8 years ago

Is it just me or Golang started gaining momentum recently? More and more related articles/OSS projects/HN links show up every day.

  • lurker- 8 years ago

    When I first saw Go I was put off by its syntax, but after giving it a chance I very quickly fell in love with it.

    I've used C#, Python, Ruby, Java, C, Obj-C, JS and Go for mid-large scale projects. Go is the only language I've ever truly loved; sometimes I even feel like I'm writing poetry (as ridiculous as that may sound).

    The community is really incredible^, I've yet to encounter anything that didn't have great documentation or solved by packages. My favorite SO answer of any language is probably this one by icza: https://stackoverflow.com/questions/22892120/how-to-generate... . I also feel that it's very easy to read and understand other peoples code compared to other languages (imo, the only aspect of Go that I think can be difficult for newcomers to grasp is pointers). All in all, I feel very confident that I'll still be writing Go code after ten years.

    ^ (Although I hate when certain "elitists" downvote questions because they feel they've been sufficiently answered elsewhere.. if a SO answer says how to display time to YYYY-MM-DD:HH-MM then don't complain if someone ask how to display time as YYYY-MM-DD.. I have a strong dislike towards jquery (or rather JS), but I think the great thing about jquery is that every imaginable edge-case seem to be documented)

    • sAbakumoff 8 years ago

      Yeah, I also love Golang, though I am a full-job front-end developer. Sometimes it can make me shout "WHAT THE FUCK"[1] to the IDE, but it's the most enjoyable language I worked with during last 20 years.

      [1] http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in...

    • scaryclam 8 years ago

      Genuine question as I've only dabbled in Go, but I've heard complaints from other dabblers that Go seems to encourage large files rather than breaking things up in a more modular fashion. Is that a reality? Or has the complainer just been unlucky in the code they've viewed?

      • fmpwizard 8 years ago

        I have been using Go for about 4 years at work and I would say they have been unlucky with the code they have looked at. You have the freedom to organize your code as you wish, you can easily go from one extreme to the other, one function per file to 1000 in one file. The only thing that isn't encouraged is to have very small packages, for example, if your project ends up split into 10 packages, but each of them is just one file (or one code file plus a test file), then most Go developers would suggest to group more files into a single package.

        • sethammons 8 years ago

          To add some meat onto that: a package should be usable (and reusable) on its own. If you have a package that is a single function or struct, it is unlikely (but still possible!) to be useful on its own and likely requires the context of your other packages to be useful.

      • Cthulhu_ 8 years ago

        I've only dabbled myself, but I can see how that would start; I come from a Java background which forces you to have one module / class per file, but Go doesn't. It's very easy to start hacking up a thing, and it's easier in development to just keep it in one file. Of course, the nature of code is that it grows, so spend enough time there and it'll start growing. If you're familiar with the code (as in, you wrote it yourself), single files shouldn't be a problem.

        It's not uncommon in other projects either, NodeJS for example has a relatively small number of large files (https://github.com/nodejs/node/blob/master/src/node.cc).

      • geodel 8 years ago

        Go definitely prefers modular fashion. But definitely no gratuitous files/packages structure like Java where a dozen packages each with 2-3 files having nothing more than 50 lines of code out of which 30 are comments and imports of another dozen packages.

        Unlike Java, Go does not have limitation of having each public class in its own file. So public symbols of any type can be put together in same file if it makes sense. Go prefers arranging code what makes sense for application functionality instead of auto-generated scaffolding like 'handlers', 'utils', 'assets', 'entities' etc like I do in my Java code.

      • richardknop 8 years ago

        Most of Go code I was working on or contributed to usually has quite a split out structure and more complex structs are defined in multiple files with related methods grouped together. I have seen couple of Go packages which consist of one huge file but I think it's quite rare. Most people will structure their code into multiple files to keep it more readable/maintainable and file sizes relatively small.

      • insertnickname 8 years ago

        I don't see any reason why Go would encourage large files. A Go package consists of every Go source file in a directory. You can use as many or as few files as you want per package.

        • captncraig 8 years ago

          We don't really have the "one class one file" beat into us like in java or c#. That means you gotta think a little to see how a package naturally splits up. Some people are better at that then others.

        • scaryclam 8 years ago

          Yeah, I found it a strange assertion to make, so was wondering if it held any water. Sometimes different languages have different ways of working, which seem odd to novices entering the space from a different background, so I didn't want to assume that they were wrong.

          Looks like it may be a case of coming across some less well written projects and making assumptions about the entire language, which is nice as Go seems fun :)

  • terminalcommand 8 years ago

    I think Golang is very suitable for network programming tasks. It gives you wonderful libraries to work with sockets, strict rules to structure your code, automatic memory management, goroutines for concurrent programming etc.

    Most network related small apps were written in C, now you can write them in Go. With the added benefit of simple libraries, memory management and goroutines. You don't have to mess arround with platform specific sockets, threading libraries etc. Plus every piece of code you open is written in understandable Go. With C, there is years of baggage, multiple standards, pre-compiled headers, undefined behaviour etc.

    And lastly, new is always more exciting than old :)

  • ikeyany 8 years ago

    No it's not you [0]. Rust, Go, R, and Python have the highest year-to-year growth.

    [0] https://stackoverflow.blog/2017/09/06/incredible-growth-pyth...

    • Cthulhu_ 8 years ago

      Python is interesting in that list, given how it's at least 4 times as old as all of the other ones in that list. What's behind that? I don't recall any major developments after Python 3, and most of the news behind that one was about its backwards incompatibility (and currently how 2.x isn't about to go anytime soon)

Kurtz79 8 years ago

Nice, I'll try it out once I get home.

A couple of question:

- What is the throughput once you fixed the issues ?

- If you were to implement a client for mobile (iOS, Android), how would you go about it ? (Just theoretically, I understand it's a personal project)

I'm using openvpn on a cloud server and one of the big advantages is the availability of mobile client apps.

  • twitchyliquid64OP 8 years ago

    Throughput: It depends on the link, but I'm getting 16mbps peak where my connection to my ISP gets me 20mbps peak.

    Mobile: You have to use the APIs that are available on the platform to hook into the network layer. After that its pretty straightforward though - you open some TLS connections, do verification, and encapsulate network traffic in some simple structs.

Retr0spectrum 8 years ago

sshuttle is another great tool with a similar use case. One advantage is that it doesn't require any server setup at all, as long as you have ssh access.

https://github.com/sshuttle/sshuttle

hamandcheese 8 years ago

In other comments the author seems to already be aware, but for anyone wondering why TCP over TCP is less than ideal, this is a good read: http://sites.inka.de/bigred/devel/tcp-tcp.html

e12e 8 years ago

Am I reading this correctly in that this uses TLS - and ends up tunneling TCP and UDP over TCP?

  • twitchyliquid64OP 8 years ago

    Correct. While simple, this does have the performance impact you're alluding to. On my 20mbps (down) connection, I peak out at 16mbps on subnet.

    The 'double congestion-control' effect can be alleviated by opening 10 or so TLS connections and pumping the packets down those, to spread the effects of TCP congestion control.

astockwell 8 years ago

Does this work on Windows? I see the TODO item "Get working on OSX", but if this project could bring x-compatibility on the big 3 platforms (thanks Go!), that could really set it apart.

  • twitchyliquid64OP 8 years ago

    I'm afraid not :/ Windows is a whole new kettle of fish to get working - you need a device driver to emulate TUN/TAP.

    That said, I'm using a library called Water for the low-level networking, and that library just added support for Windows. Implementing full windows support only requires you to implement a few network methods (such as helpers_linux.go) - PRs welcome :)

userbinator 8 years ago

Upon reading the title I wondered "would anyone ever create a VPN client that doesn't use encryption?" and thought, with the "2k lines" as additional evidence, that it was the source code which was somehow encrypted/obfuscated to e.g. prevent censorship...

I was also expecting to see a single file at that line count, but then again I'm not really familiar with Go. Is this style of "many tiny files in multiple nested directories" common/expected for Go? I know it's rather common in many other languages, but also not what I expect when I see "Simple" or explicit mention of a low line count.

  • tyingq 8 years ago

    >would anyone ever create a VPN client that doesn't use encryption?"

    They do, but generally call it tunneling. L2TP and GRE links that don't use IPSEC are fairly common on private WANs.

    I suspect the author was trying to point out that the encryption was included in the 2k lines, versus say, calling out to ssh.

  • captncraig 8 years ago

    I wouldn't use that repo as a representative of what "go code looks like". Most go repos are pretty similar in "structure", but I really don't know how to navigate this. The 'src' directory looks like the author is really fighting the gopath concept, but also trying to vendor dependencies. I agree, if my hook was "in xx lines of code" I would try to avoid boilerplate and keep it all together as much as possible.

_joel 8 years ago

I guess the main question is why should I use/trust this above OpenVPN/Tinc or WireGuard etc?

  • twitchyliquid64OP 8 years ago

    I'm glad you're asking these kinds of questions, they need to come up more often especially in a software-supply-chain context.

    I am a strong advocate of the saying 'trust but verify'. I believe you should closely audit whatever OSS software you are looking at using in light of your threat model.

    To get round to your question: Why should I use subnet over OpenVPN/Tinc etc? That decision is entirely your prerogative. Subnet is small (quick(er) to audit), easy to understand, and has the bare minimum functionality needed to implement a VPN with full mutual authentication. OpenVPN and others have far more features and are almost certainty xx% faster. Where you want to draw the line is up to you.

  • thyrsus 8 years ago

    It appears all the ISPs I use have figured out how to kill OpenVPN after a few Mbytes have passed, resulting in annoying VPN service interruptions and restarts (I need to figure out how to restart it automatically) - and the browser reacts to the interrupted transfer by restarting it on the now VPNless network connection. Obscurity might be a defense against this (but wouldn't be if one were targeted instead of getting caught in a driftnet).

    • _joel 8 years ago

      That's not been my experience with OpenVPN. It's setup to reconnect to the VPN and only route traffic via the VPN (separate box, actually a repurposed old laptop). Take a look at ping and ping-restart options

      • thyrsus 8 years ago

        Thanks for the suggestions, but decreasing the ping interval only made the VPN fail faster, and there was no difference in behavior between ping-restart and ping-exit :-(.

  • ivanfon 8 years ago

    Because you can easily read and understand the code.

    • dsacco 8 years ago

      For what it’s worth, this only really applies to a comparison against OpenVPN or IPSec. WireGuard has similar code complexity and size, and is approximately the same when compared against the incumbent VPN options.

      • zokier 8 years ago

        I don't think the comparison to Wireguard is apples-to-apples. Wireguard implements it's own semi-custom cryptosystem (Noise) whereas subnet rides on top of Go standard TLS implementation. So depending on how you view things, Wireguard is either much simpler (if you compare to the whole TLS stack) or much more complex (if you assume Go TLS to be reliable/trustworthy)

      • zx2c4 8 years ago

        Maybe I misunderstood your comment, but WireGuard is less than 4k LoC, which is a few orders of magnitude smaller than OpenVPN or IPsec.

        • dsacco 8 years ago

          Yep you misunderstood, I was saying WireGuard has similar code complexity to the Go VPN implementation linked here :)

  • hyperbovine 8 years ago

    Because your government banned those.

perlpimp 8 years ago

language used in the project is Erlang, not Go.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection