2 govpn -- high-performance secure virtual private network daemon
3 Copyright (C) 2014 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 "code.google.com/p/go.crypto/poly1305"
32 "code.google.com/p/go.crypto/salsa20"
36 remoteAddr = flag.String("remote", "", "Remote server address")
37 bindAddr = flag.String("bind", "", "Bind to address")
38 ifaceName = flag.String("iface", "tap0", "TAP network interface")
39 keyPath = flag.String("key", "", "Path to authentication key file")
40 mtu = flag.Int("mtu", 1500, "MTU")
41 timeoutP = flag.Int("timeout", 60, "Timeout seconds")
42 verboseP = flag.Bool("v", false, "Increase verbosity")
48 // S20BS is Salsa20's internal blocksize in bytes
59 key *[KeySize]byte // encryption key
60 nonceOur uint64 // nonce for our messages
61 nonceRecv uint64 // latest received nonce from remote peer
73 log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
76 keyData, err := ioutil.ReadFile(*keyPath)
78 panic("Unable to read keyfile: " + err.Error())
80 if len(keyData) < 64 {
81 panic("Key must be 64 hex characters long")
83 keyDecoded, err := hex.DecodeString(string(keyData[0:64]))
85 panic("Unable to decode the key: " + err.Error())
87 key := new([KeySize]byte)
88 copy(key[:], keyDecoded)
92 // Interface listening
93 maxIfacePktSize := *mtu - poly1305.TagSize - NonceSize
94 log.Println("Max MTU", maxIfacePktSize, "on interface", *ifaceName)
95 iface := NewTAP(*ifaceName)
96 ethBuf := make([]byte, maxIfacePktSize)
97 ethSink := make(chan int)
98 ethSinkReady := make(chan bool)
102 n, err := iface.Read(ethBuf)
111 // Network address parsing
112 if (len(*bindAddr) > 1 && len(*remoteAddr) > 1) ||
113 (len(*bindAddr) == 0 && len(*remoteAddr) == 0) {
114 panic("Either -bind or -remote must be specified only")
116 var conn *net.UDPConn
117 var remote *net.UDPAddr
119 bindTo := "0.0.0.0:0"
121 if len(*bindAddr) > 1 {
126 bind, err := net.ResolveUDPAddr("udp", bindTo)
130 conn, err = net.ListenUDP("udp", bind)
135 if len(*remoteAddr) > 1 {
136 remote, err = net.ResolveUDPAddr("udp", *remoteAddr)
142 udpBuf := make([]byte, *mtu)
143 udpSink := make(chan *UDPPkt)
144 udpSinkReady := make(chan bool)
145 go func(conn *net.UDPConn) {
148 conn.SetReadDeadline(time.Now().Add(time.Second))
149 n, addr, err := conn.ReadFromUDP(udpBuf)
156 udpSink <- &UDPPkt{addr, n}
164 var udpPktData []byte
171 states := make(map[string]*Handshake)
172 nonce := make([]byte, NonceSize)
173 keyAuth := new([KeySize]byte)
174 tag := new([poly1305.TagSize]byte)
175 buf := make([]byte, *mtu+S20BS)
176 emptyKey := make([]byte, KeySize)
177 ethPkt := make([]byte, maxIfacePktSize)
178 udpPktDataBuf := make([]byte, *mtu)
181 states[remote.String()] = HandshakeStart(conn, remote, key)
190 case udpPkt = <-udpSink:
192 if !serverMode && timeouts >= timeout {
199 copy(udpPktDataBuf, udpBuf[:udpPkt.size])
201 udpPktData = udpPktDataBuf[:udpPkt.size]
202 if isValidHandshakePkt(udpPktData) {
203 addr = udpPkt.addr.String()
204 state, exists := states[addr]
207 state = &Handshake{addr: udpPkt.addr}
210 p = state.Server(conn, key, udpPktData)
216 p = state.Client(conn, key, udpPktData)
228 nonceRecv, _ := binary.Uvarint(udpPktData[:8])
229 if peer.nonceRecv >= nonceRecv {
233 copy(buf[:KeySize], emptyKey)
234 copy(tag[:], udpPktData[udpPkt.size-poly1305.TagSize:])
235 copy(buf[S20BS:], udpPktData[NonceSize:udpPkt.size-poly1305.TagSize])
236 salsa20.XORKeyStream(
237 buf[:S20BS+udpPkt.size-poly1305.TagSize],
238 buf[:S20BS+udpPkt.size-poly1305.TagSize],
239 udpPktData[:NonceSize],
242 copy(keyAuth[:], buf[:KeySize])
243 if !poly1305.Verify(tag, udpPktData[:udpPkt.size-poly1305.TagSize], keyAuth) {
247 peer.nonceRecv = nonceRecv
249 if _, err := iface.Write(buf[S20BS : S20BS+udpPkt.size-NonceSize-poly1305.TagSize]); err != nil {
250 log.Println("Error writing to iface: ", err)
255 case ethPktSize = <-ethSink:
256 if ethPktSize > maxIfacePktSize {
257 panic("Too large packet on interface")
263 copy(ethPkt, ethBuf[:ethPktSize])
265 peer.nonceOur = peer.nonceOur + 2
266 binary.PutUvarint(nonce, peer.nonceOur)
267 copy(buf[:KeySize], emptyKey)
268 copy(buf[S20BS:], ethPkt[:ethPktSize])
269 salsa20.XORKeyStream(buf, buf, nonce, peer.key)
270 copy(buf[S20BS-NonceSize:S20BS], nonce)
271 copy(keyAuth[:], buf[:KeySize])
272 dataToSend := buf[S20BS-NonceSize : S20BS+ethPktSize]
273 poly1305.Sum(tag, dataToSend, keyAuth)
274 if _, err := conn.WriteTo(append(dataToSend, tag[:]...), peer.addr); err != nil {
275 log.Println("Error sending UDP", err)