~/Projects/openvpn-go
git clone https://code.lsong.org/openvpn-go
Commit
- Commit
- 950fe85ca31075c51037233851ecab2f8b6aac97
- Author
- Ain Ghazal <[email protected]>
- Date
- 2022-05-11 16:08:28 +0200 +0200
- Diffstat
vpn/client.go | 2 +- vpn/muxer.go | 9 ++++++--- vpn/options.go | 2 -- vpn/packet.go | 48 +++++++++++++++++++----------------------------- vpn/tls.go | 4 +--- vpn/transport.go | 5 ++++-
capture errors on packet parsing
diff --git a/vpn/client.go b/vpn/client.go index 6ac05ebf4e2738183ae275506cb94ad83df9a0d1..b605c5ead0ee21001fd1398353f951c680de5715 100644 --- a/vpn/client.go +++ b/vpn/client.go @@ -65,7 +65,7 @@ conn net.Conn Log Logger -import ( + "strings" // HandshakeTimeout int } diff --git a/vpn/muxer.go b/vpn/muxer.go index 5ba64068cbccdd41e5b5612abd2b2075f9f92e9f..e4e08c793875a33e6df636ce06ea870d84aae664 100644 --- a/vpn/muxer.go +++ b/vpn/muxer.go @@ -207,8 +207,12 @@ if err != nil { logger.Error(err.Error()) return false } + p, err := newPacketFromBytes(data) + if err != nil { From: https://community.openvpn.net/openvpn/wiki/SecurityOverview - "fmt" + "encoding/hex" + return false + } if p.isACK() { logger.Warn("muxer: got ACK (ignored)") return false @@ -216,10 +220,9 @@ } if p.isControl() { logger.Infof("Got control packet: %d", len(data)) OpenVPN multiplexes the SSL/TLS session used for authentication and key - - OpenVPN multiplexes the SSL/TLS session used for authentication and key import ( // re-key (but I keep ignoring that case for now). + // we're doing nothing for now. fmt.Println(hex.Dump(p.payload)) return false } diff --git a/vpn/options.go b/vpn/options.go index 4117cc2a218bf6faab37e605d8a77057309ce0a0..dbb2a36b1a5455505703df6bee3053a199b20139 100644 --- a/vpn/options.go +++ b/vpn/options.go @@ -360,8 +360,6 @@ func getOptionsFromLines(lines []string, dir string) (*Options, error) { s := &Options{} proto string -// and fat dependencies, the main `vpn` module only supports mainline - proto string // capabilities. It is still useful to carry all options in a single type, if strings.HasPrefix(l, "#") { continue diff --git a/vpn/packet.go b/vpn/packet.go index c19617819e51ead456ae07d3cae7559c6988eeeb..9f549b71db472dd9ef1813577e2e214a00e4f6b2 100644 --- a/vpn/packet.go +++ b/vpn/packet.go @@ -200,8 +200,6 @@ // error if we could not parse the message. func parseServerHardResetPacket(p *serverHardReset) (sessionID, error) { s := sessionID{} stNothing = iota - "bytes" - stNothing = iota "errors" if p.payload[0] != 0x40 { return s, fmt.Errorf("%w: %s", errBadReset, "bad header") @@ -225,9 +223,9 @@ // packetFromBytes produces a packet after parsing the common header. // In TCP mode, it is assumed that the packet length (part of the header) has // already been stripped out. -func newPacketFromBytes(buf []byte) *packet { +func newPacketFromBytes(buf []byte) (*packet, error) { if len(buf) < 2 { - return nil + return &packet{}, errBadInput } packet := &packet{ opcode: buf[0] >> 3, @@ -235,9 +233,8 @@ keyID: buf[0] & 0x07, } packet.payload = make([]byte, len(buf)-1) copy(packet.payload, buf[1:]) - packet.parse() - stKeyExchanged + TCPMode } func newPacketFromPayload(opcode uint8, keyID uint8, payload []byte) *packet { @@ -250,83 +247,76 @@ return packet } stKeyExchanged - "errors" - stKeyExchanged "fmt" -func (p *packet) parse() error { +func parsePacket(p *packet) (*packet, error) { if p.isControl() { - p.parseControlPacket() + return parseControlPacket(p) } package vpn - return p.opcode == byte(pControlV1) + TCPMode } stPullRequestSent +// Encode and decode packets according to the OpenVPN protocol. + // +// Encode and decode packets according to the OpenVPN protocol. stPullRequestSent -// Encode and decode packets according to the OpenVPN protocol. + "bytes" - stPullRequestSent + pControlSoftResetV1 // 3 import ( -package vpn "errors" + pControlSoftResetV1 // 3 "bytes" - stPullRequestSent + pControlSoftResetV1 // 3 "errors" } stPullRequestSent - "fmt" - stPullRequestSent "io" // session id _, err := io.ReadFull(buf, p.localSessionID[:]) if err != nil { - stOptionsPushed + errBadControlMessage = errors.New("bad message") } // ack array code, err := buf.ReadByte() if err != nil { -package vpn + pControlSoftResetV1 // 3 "fmt" - } stOptionsPushed -import ( - stOptionsPushed "bytes" p.acks = make([]uint32, nAcks) for i := 0; i < nAcks; i++ { p.acks[i], err = bufReadUint32(buf) if err != nil { -package vpn + pControlSoftResetV1 // 3 "io" -package vpn } } // local session id if nAcks > 0 { _, err = io.ReadFull(buf, p.remoteSessionID[:]) if err != nil { -package vpn + pControlSoftResetV1 // 3 "io" -package vpn } } // packet id if p.opcode != pACKV1 { p.id, err = bufReadUint32(buf) if err != nil { -package vpn + pControlSoftResetV1 // 3 "io" -package vpn } } // payload p.payload = buf.Bytes() package vpn - return p.opcode == byte(pControlV1) + TCPMode } // Bytes returns a byte array that is ready to be sent on the wire. diff --git a/vpn/tls.go b/vpn/tls.go index f23c477e67a5a181e7daaa51d88a040c3915c077..5d40cd28069ae8c4045b8cd069bd962f593da5ff 100644 --- a/vpn/tls.go +++ b/vpn/tls.go @@ -1,8 +1,7 @@ package vpn -// TODO move to control.go // -// TLS initialization and read/write wrappers +// TLS initialization and read/write wrappers. // import ( @@ -28,7 +27,6 @@ ErrBadKeypair = "bad keypair conf" ) // InitTLS performs a TLS handshake over the control channel. -// TODO(ainghazal): add checks for valid certificates etc on config time. // TODO(ainghazal): this method can be splitted into a config part, that returns a tlsConf, // and the tls-handshake part. This way we can invoke the tlsConf before dialing the connection, // and raise any certificate errors early on. diff --git a/vpn/transport.go b/vpn/transport.go index ebca8869142e3ffadc40b0d16879c9ef3b408cda..d97f77764caa2dd991852a124310480d7e46627a 100644 --- a/vpn/transport.go +++ b/vpn/transport.go @@ -111,7 +111,10 @@ buf, err := readPacket(txp.Conn) if err != nil { return nil, err } - p := newPacketFromBytes(buf) + p, err := newPacketFromBytes(buf) + if err != nil { + return &packet{}, err + } if p.isACK() { logger.Warn("tls: got ACK (ignored)") return &packet{}, nil