
Show HN: Encrypted VPN in 2k lines of Go - twitchyliquid64
https://github.com/twitchyliquid64/subnet
======
arianvanp
Related: Wireguard is a new VPN for linux in 4k lines of C
[https://www.wireguard.com/](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.

~~~
twitchyliquid64
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
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](https://noiseprotocol.org)

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

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

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

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

[6]
[https://github.com/twitchyliquid64/subnet/blob/50fc8fe2b6ccf...](https://github.com/twitchyliquid64/subnet/blob/50fc8fe2b6ccf72a1f34e756d843238ab9b42312/src/subnet/server.go#L132)

~~~
twitchyliquid64
> 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
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.

------
sethammons
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](https://github.com/twitchyliquid64/subnet/issues/3).

~~~
twitchyliquid64
Thanks! This is definitely something I need to get around to once I read up a
bit more on vendoring.

~~~
freedomben
Check out the `dep` tool:
[https://github.com/golang/dep](https://github.com/golang/dep)

It is the future of official vendoring tools.

You could also look at `govendor`:
[https://github.com/kardianos/govendor](https://github.com/kardianos/govendor)

I've used govendor in some projects and found it agreeable. Best of luck :-)

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

~~~
lurker-
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...](https://stackoverflow.com/questions/22892120/how-to-generate-a-
random-string-of-a-fixed-length-in-golang) . 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)

~~~
scaryclam
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?

~~~
insertnickname
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
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.

------
Kurtz79
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.

~~~
twitchyliquid64
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
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](https://github.com/sshuttle/sshuttle)

~~~
zx2c4
A neat thing about sshuttle is that it restreams TCP connections inside of the
SSH tunnel so that you don't incur the classic TCP-over-TCP problem [1].

[1] [http://sshuttle.readthedocs.io/en/stable/how-it-
works.html](http://sshuttle.readthedocs.io/en/stable/how-it-works.html)

------
hamandcheese
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](http://sites.inka.de/bigred/devel/tcp-tcp.html)

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

~~~
twitchyliquid64
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
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.

~~~
twitchyliquid64
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
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
>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.

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

~~~
thyrsus
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
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
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 :-(.

------
perlpimp
language used in the project is Erlang, not Go.

~~~
zingmars
What do you mean? I don't think I saw a single Erlang file in that repository.

~~~
perlpimp
beg a pardon, was looking at the other submission.

