Desuglify a bit

This commit is contained in:
Frank Denis 2018-01-09 13:27:03 +01:00
parent 9ffa61c9e3
commit 60a58067c1
3 changed files with 92 additions and 64 deletions

View File

@ -1,7 +1,6 @@
package main
import (
"errors"
"time"
)
@ -16,9 +15,9 @@ const (
var (
CertMagic = [4]byte{0x44, 0x4e, 0x53, 0x43}
ServerMagic = [8]byte{0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38}
MinDNSPacketSize = uint(12)
MaxDNSPacketSize = uint(4096)
InitialMinQuestionSize = uint(128)
MinDNSPacketSize = 12
MaxDNSPacketSize = 4096
InitialMinQuestionSize = 128
TimeoutMin = 1 * time.Second
TimeoutMax = 5 * time.Second
)
@ -26,28 +25,3 @@ var (
func HasTCFlag(packet []byte) bool {
return packet[2]&2 == 2
}
func Pad(packet []byte, minSize uint) []byte {
packet = append(packet, 0x80)
for uint(len(packet)) < minSize {
packet = append(packet, 0)
}
return packet
}
func Unpad(packet []byte) ([]byte, error) {
i := len(packet)
for {
if i == 0 {
return nil, errors.New("Invalid padding (short packet)")
}
i--
if packet[i] == 0x80 {
break
}
if packet[i] != 0x00 {
return nil, errors.New("Invalid padding (delimiter not found)")
}
}
return packet[:i], nil
}

68
crypto.go Normal file
View File

@ -0,0 +1,68 @@
package main
import (
"bytes"
"crypto/rand"
"errors"
"github.com/jedisct1/xsecretbox"
)
const (
NonceSize = xsecretbox.NonceSize
HalfNonceSize = xsecretbox.NonceSize / 2
TagSize = xsecretbox.TagSize
)
func pad(packet []byte, minSize int) []byte {
packet = append(packet, 0x80)
for len(packet) < minSize {
packet = append(packet, 0)
}
return packet
}
func unpad(packet []byte) ([]byte, error) {
for i := len(packet); ; {
if i == 0 {
return nil, errors.New("Invalid padding (short packet)")
}
i--
if packet[i] == 0x80 {
return packet[:i], nil
} else if packet[i] != 0x00 {
return nil, errors.New("Invalid padding (delimiter not found)")
}
}
}
func (proxy *Proxy) Crypt(serverInfo *ServerInfo, packet []byte) (encrypted []byte, clientNonce []byte) {
nonce, clientNonce := make([]byte, NonceSize), make([]byte, HalfNonceSize)
rand.Read(clientNonce)
copy(nonce, clientNonce)
encrypted = append(serverInfo.MagicQuery[:], proxy.proxyPublicKey[:]...)
encrypted = append(encrypted, nonce[:HalfNonceSize]...)
encrypted = xsecretbox.Seal(encrypted, nonce, pad(packet, proxy.minQuestionSize), serverInfo.SharedKey[:])
return
}
func (proxy *Proxy) Decrypt(serverInfo *ServerInfo, encrypted []byte, nonce []byte) ([]byte, error) {
serverMagicLen := len(ServerMagic)
responseHeaderLen := serverMagicLen + NonceSize
if len(encrypted) < responseHeaderLen+TagSize+int(MinDNSPacketSize) ||
!bytes.Equal(encrypted[:serverMagicLen], ServerMagic[:]) {
return encrypted, errors.New("Short message")
}
serverNonce := encrypted[serverMagicLen:responseHeaderLen]
if !bytes.Equal(nonce[:HalfNonceSize], serverNonce[:HalfNonceSize]) {
return encrypted, errors.New("Unexpected nonce")
}
packet, err := xsecretbox.Open(nil, serverNonce, encrypted[responseHeaderLen:], serverInfo.SharedKey[:])
if err != nil {
return encrypted, errors.New("Incorrect tag")
}
packet, err = unpad(packet)
if err != nil || len(packet) < MinDNSPacketSize {
return encrypted, errors.New("Incorrect padding")
}
return packet, nil
}

View File

@ -1,7 +1,6 @@
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"fmt"
@ -10,7 +9,6 @@ import (
"strings"
"time"
"github.com/jedisct1/xsecretbox"
"golang.org/x/crypto/curve25519"
"golang.org/x/crypto/ed25519"
)
@ -18,7 +16,7 @@ import (
type Proxy struct {
proxyPublicKey [32]byte
proxySecretKey [32]byte
minQuestionSize uint
minQuestionSize int
serversInfo []ServerInfo
}
@ -88,14 +86,19 @@ type ServerInfo struct {
TCPAddr *net.TCPAddr
}
func (proxy *Proxy) adjustMinQuestionSize() {
if MaxDNSPacketSize-proxy.minQuestionSize < proxy.minQuestionSize {
proxy.minQuestionSize = MaxDNSPacketSize
} else {
proxy.minQuestionSize *= 2
}
}
func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, packet []byte, clientAddr net.Addr, clientPc net.PacketConn) {
packet = Pad(packet, proxy.minQuestionSize)
nonce := make([]byte, xsecretbox.NonceSize)
rand.Read(nonce[0 : xsecretbox.NonceSize/2])
encrypted := serverInfo.MagicQuery[:]
encrypted = append(encrypted, proxy.proxyPublicKey[:]...)
encrypted = append(encrypted, nonce[:xsecretbox.NonceSize/2]...)
encrypted = xsecretbox.Seal(encrypted, nonce, packet, serverInfo.SharedKey[:])
if len(packet) < MinDNSPacketSize {
return
}
encrypted, clientNonce := proxy.Crypt(serverInfo, packet)
pc, err := net.DialUDP("udp", nil, serverInfo.UDPAddr)
if err != nil {
return
@ -103,38 +106,21 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, packet []byte,
defer pc.Close()
pc.SetDeadline(time.Now().Add(serverInfo.Timeout))
pc.Write(encrypted)
buffer := make([]byte, MaxDNSPacketSize)
length, err := pc.Read(buffer)
encrypted = make([]byte, MaxDNSPacketSize)
length, err := pc.Read(encrypted)
if err != nil {
return
}
buffer = buffer[:length]
serverMagicLen := len(ServerMagic)
responseHeaderLen := serverMagicLen + xsecretbox.NonceSize
if len(buffer) < responseHeaderLen+xsecretbox.TagSize ||
!bytes.Equal(buffer[:serverMagicLen], ServerMagic[:]) {
return
}
serverNonce := buffer[serverMagicLen:responseHeaderLen]
if !bytes.Equal(nonce[:xsecretbox.NonceSize/2], serverNonce[:xsecretbox.NonceSize/2]) {
return
}
decrypted, err := xsecretbox.Open(nil, serverNonce, buffer[responseHeaderLen:], serverInfo.SharedKey[:])
encrypted = encrypted[:length]
packet, err = proxy.Decrypt(serverInfo, encrypted, clientNonce)
if err != nil {
return
}
decrypted, err = Unpad(decrypted)
if err != nil || uint(len(decrypted)) < MinDNSPacketSize {
return
clientPc.WriteTo(packet, clientAddr)
if HasTCFlag(packet) {
proxy.adjustMinQuestionSize()
}
if HasTCFlag(decrypted) {
if MaxDNSPacketSize-proxy.minQuestionSize < proxy.minQuestionSize {
proxy.minQuestionSize = MaxDNSPacketSize
} else {
proxy.minQuestionSize *= 2
}
}
clientPc.WriteTo(decrypted, clientAddr)
}
func main() {