mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-03-04 02:14:40 +01:00
Desuglify a bit
This commit is contained in:
parent
9ffa61c9e3
commit
60a58067c1
3 changed files with 92 additions and 64 deletions
32
common.go
32
common.go
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,9 +15,9 @@ const (
|
||||||
var (
|
var (
|
||||||
CertMagic = [4]byte{0x44, 0x4e, 0x53, 0x43}
|
CertMagic = [4]byte{0x44, 0x4e, 0x53, 0x43}
|
||||||
ServerMagic = [8]byte{0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38}
|
ServerMagic = [8]byte{0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38}
|
||||||
MinDNSPacketSize = uint(12)
|
MinDNSPacketSize = 12
|
||||||
MaxDNSPacketSize = uint(4096)
|
MaxDNSPacketSize = 4096
|
||||||
InitialMinQuestionSize = uint(128)
|
InitialMinQuestionSize = 128
|
||||||
TimeoutMin = 1 * time.Second
|
TimeoutMin = 1 * time.Second
|
||||||
TimeoutMax = 5 * time.Second
|
TimeoutMax = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
@ -26,28 +25,3 @@ var (
|
||||||
func HasTCFlag(packet []byte) bool {
|
func HasTCFlag(packet []byte) bool {
|
||||||
return packet[2]&2 == 2
|
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
68
crypto.go
Normal 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
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -10,7 +9,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jedisct1/xsecretbox"
|
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
@ -18,7 +16,7 @@ import (
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
proxyPublicKey [32]byte
|
proxyPublicKey [32]byte
|
||||||
proxySecretKey [32]byte
|
proxySecretKey [32]byte
|
||||||
minQuestionSize uint
|
minQuestionSize int
|
||||||
serversInfo []ServerInfo
|
serversInfo []ServerInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,14 +86,19 @@ type ServerInfo struct {
|
||||||
TCPAddr *net.TCPAddr
|
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) {
|
func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, packet []byte, clientAddr net.Addr, clientPc net.PacketConn) {
|
||||||
packet = Pad(packet, proxy.minQuestionSize)
|
if len(packet) < MinDNSPacketSize {
|
||||||
nonce := make([]byte, xsecretbox.NonceSize)
|
return
|
||||||
rand.Read(nonce[0 : xsecretbox.NonceSize/2])
|
}
|
||||||
encrypted := serverInfo.MagicQuery[:]
|
encrypted, clientNonce := proxy.Crypt(serverInfo, packet)
|
||||||
encrypted = append(encrypted, proxy.proxyPublicKey[:]...)
|
|
||||||
encrypted = append(encrypted, nonce[:xsecretbox.NonceSize/2]...)
|
|
||||||
encrypted = xsecretbox.Seal(encrypted, nonce, packet, serverInfo.SharedKey[:])
|
|
||||||
pc, err := net.DialUDP("udp", nil, serverInfo.UDPAddr)
|
pc, err := net.DialUDP("udp", nil, serverInfo.UDPAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -103,38 +106,21 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, packet []byte,
|
||||||
defer pc.Close()
|
defer pc.Close()
|
||||||
pc.SetDeadline(time.Now().Add(serverInfo.Timeout))
|
pc.SetDeadline(time.Now().Add(serverInfo.Timeout))
|
||||||
pc.Write(encrypted)
|
pc.Write(encrypted)
|
||||||
buffer := make([]byte, MaxDNSPacketSize)
|
|
||||||
length, err := pc.Read(buffer)
|
encrypted = make([]byte, MaxDNSPacketSize)
|
||||||
|
length, err := pc.Read(encrypted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buffer = buffer[:length]
|
encrypted = encrypted[:length]
|
||||||
serverMagicLen := len(ServerMagic)
|
packet, err = proxy.Decrypt(serverInfo, encrypted, clientNonce)
|
||||||
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[:])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
decrypted, err = Unpad(decrypted)
|
clientPc.WriteTo(packet, clientAddr)
|
||||||
if err != nil || uint(len(decrypted)) < MinDNSPacketSize {
|
if HasTCFlag(packet) {
|
||||||
return
|
proxy.adjustMinQuestionSize()
|
||||||
}
|
}
|
||||||
if HasTCFlag(decrypted) {
|
|
||||||
if MaxDNSPacketSize-proxy.minQuestionSize < proxy.minQuestionSize {
|
|
||||||
proxy.minQuestionSize = MaxDNSPacketSize
|
|
||||||
} else {
|
|
||||||
proxy.minQuestionSize *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clientPc.WriteTo(decrypted, clientAddr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue