April 1st is already over in some time zones :)
This reverts commit dac52ab42a
.
This commit is contained in:
parent
dac52ab42a
commit
adb0c94a61
|
@ -43,6 +43,7 @@ type Config struct {
|
|||
SourceRequireDNSSEC bool `toml:"require_dnssec"`
|
||||
SourceRequireNoLog bool `toml:"require_nolog"`
|
||||
SourceRequireNoFilter bool `toml:"require_nofilter"`
|
||||
SourceDNSCrypt bool `toml:"dnscrypt_servers"`
|
||||
SourceDoH bool `toml:"doh_servers"`
|
||||
SourceIPv4 bool `toml:"ipv4_servers"`
|
||||
SourceIPv6 bool `toml:"ipv6_servers"`
|
||||
|
@ -71,6 +72,7 @@ func newConfig() Config {
|
|||
SourceRequireNoFilter: true,
|
||||
SourceIPv4: true,
|
||||
SourceIPv6: false,
|
||||
SourceDNSCrypt: true,
|
||||
SourceDoH: true,
|
||||
MaxClients: 250,
|
||||
FallbackResolver: DefaultFallbackResolver,
|
||||
|
@ -285,6 +287,7 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error {
|
|||
config.SourceRequireNoLog = false
|
||||
config.SourceIPv4 = true
|
||||
config.SourceIPv6 = true
|
||||
config.SourceDNSCrypt = true
|
||||
config.SourceDoH = true
|
||||
}
|
||||
|
||||
|
@ -435,7 +438,8 @@ func (config *Config) loadSource(proxy *Proxy, requiredProps ServerInformalPrope
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !(config.SourceDoH && registeredServer.stamp.proto == StampProtoTypeDoH) {
|
||||
if !((config.SourceDNSCrypt && registeredServer.stamp.proto == StampProtoTypeDNSCrypt) ||
|
||||
(config.SourceDoH && registeredServer.stamp.proto == StampProtoTypeDoH)) {
|
||||
continue
|
||||
}
|
||||
dlog.Debugf("Adding [%s] to the set of wanted resolvers", registeredServer.name)
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jedisct1/dlog"
|
||||
"github.com/jedisct1/xsecretbox"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/nacl/box"
|
||||
)
|
||||
|
||||
type CertInfo struct {
|
||||
ServerPk [32]byte
|
||||
SharedKey [32]byte
|
||||
MagicQuery [ClientMagicLen]byte
|
||||
CryptoConstruction CryptoConstruction
|
||||
ForwardSecurity bool
|
||||
}
|
||||
|
||||
func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk ed25519.PublicKey, serverAddress string, providerName string, isNew bool) (CertInfo, int, error) {
|
||||
if len(pk) != ed25519.PublicKeySize {
|
||||
return CertInfo{}, 0, errors.New("Invalid public key length")
|
||||
}
|
||||
if !strings.HasSuffix(providerName, ".") {
|
||||
providerName = providerName + "."
|
||||
}
|
||||
if serverName == nil {
|
||||
serverName = &providerName
|
||||
}
|
||||
query := new(dns.Msg)
|
||||
query.SetQuestion(providerName, dns.TypeTXT)
|
||||
client := dns.Client{Net: proto, UDPSize: uint16(MaxDNSUDPPacketSize)}
|
||||
in, rtt, err := client.Exchange(query, serverAddress)
|
||||
if err != nil {
|
||||
dlog.Noticef("[%s] TIMEOUT", *serverName)
|
||||
return CertInfo{}, 0, err
|
||||
}
|
||||
now := uint32(time.Now().Unix())
|
||||
certInfo := CertInfo{CryptoConstruction: UndefinedConstruction}
|
||||
highestSerial := uint32(0)
|
||||
for _, answerRr := range in.Answer {
|
||||
binCert, err := packTxtString(strings.Join(answerRr.(*dns.TXT).Txt, ""))
|
||||
if err != nil {
|
||||
dlog.Warnf("[%v] Unable to unpack the certificate", providerName)
|
||||
continue
|
||||
}
|
||||
if len(binCert) < 124 {
|
||||
dlog.Warnf("[%v] Certificate too short", providerName)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(binCert[:4], CertMagic[:4]) {
|
||||
dlog.Warnf("[%v] Invalid cert magic", providerName)
|
||||
continue
|
||||
}
|
||||
cryptoConstruction := CryptoConstruction(0)
|
||||
switch esVersion := binary.BigEndian.Uint16(binCert[4:6]); esVersion {
|
||||
case 0x0001:
|
||||
cryptoConstruction = XSalsa20Poly1305
|
||||
case 0x0002:
|
||||
cryptoConstruction = XChacha20Poly1305
|
||||
default:
|
||||
dlog.Noticef("[%v] Unsupported crypto construction", providerName)
|
||||
continue
|
||||
}
|
||||
signature := binCert[8:72]
|
||||
signed := binCert[72:]
|
||||
if !ed25519.Verify(pk, signed, signature) {
|
||||
dlog.Warnf("[%v] Incorrect signature", providerName)
|
||||
continue
|
||||
}
|
||||
serial := binary.BigEndian.Uint32(binCert[112:116])
|
||||
tsBegin := binary.BigEndian.Uint32(binCert[116:120])
|
||||
tsEnd := binary.BigEndian.Uint32(binCert[120:124])
|
||||
if tsBegin >= tsEnd {
|
||||
dlog.Warnf("[%v] certificate ends before it starts (%v >= %v)", providerName, tsBegin, tsEnd)
|
||||
continue
|
||||
}
|
||||
ttl := tsEnd - tsBegin
|
||||
if ttl > 86400*7 {
|
||||
dlog.Infof("[%v] the key validity period for this server is excessively long (%d days), significantly reducing reliability and forward security.", providerName, ttl/86400)
|
||||
daysLeft := (tsEnd - now) / 86400
|
||||
if daysLeft < 1 {
|
||||
dlog.Criticalf("[%v] certificate will expire today -- Switch to a different resolver as soon as possible", providerName)
|
||||
} else if daysLeft <= 7 {
|
||||
dlog.Warnf("[%v] certificate is about to expire -- if you don't manage this server, tell the server operator about it", providerName)
|
||||
} else if daysLeft <= 30 {
|
||||
dlog.Infof("[%v] certificate will expire in %d days", providerName, daysLeft)
|
||||
}
|
||||
certInfo.ForwardSecurity = false
|
||||
} else {
|
||||
certInfo.ForwardSecurity = true
|
||||
}
|
||||
if !proxy.certIgnoreTimestamp {
|
||||
if now > tsEnd || now < tsBegin {
|
||||
dlog.Debugf("[%v] Certificate not valid at the current date", providerName)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if serial < highestSerial {
|
||||
dlog.Debugf("[%v] Superseded by a previous certificate", providerName)
|
||||
continue
|
||||
}
|
||||
if serial == highestSerial {
|
||||
if cryptoConstruction < certInfo.CryptoConstruction {
|
||||
dlog.Debugf("[%v] Keeping the previous, preferred crypto construction", providerName)
|
||||
continue
|
||||
} else {
|
||||
dlog.Debugf("[%v] Upgrading the construction from %v to %v", providerName, certInfo.CryptoConstruction, cryptoConstruction)
|
||||
}
|
||||
}
|
||||
if cryptoConstruction != XChacha20Poly1305 && cryptoConstruction != XSalsa20Poly1305 {
|
||||
dlog.Noticef("[%v] Cryptographic construction %v not supported", providerName, cryptoConstruction)
|
||||
continue
|
||||
}
|
||||
var serverPk [32]byte
|
||||
copy(serverPk[:], binCert[72:104])
|
||||
var sharedKey [32]byte
|
||||
if cryptoConstruction == XChacha20Poly1305 {
|
||||
sharedKey, err = xsecretbox.SharedKey(proxy.proxySecretKey, serverPk)
|
||||
if err != nil {
|
||||
dlog.Criticalf("[%v] Weak public key", providerName)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
box.Precompute(&sharedKey, &serverPk, &proxy.proxySecretKey)
|
||||
}
|
||||
certInfo.SharedKey = sharedKey
|
||||
highestSerial = serial
|
||||
certInfo.CryptoConstruction = cryptoConstruction
|
||||
copy(certInfo.ServerPk[:], serverPk[:])
|
||||
copy(certInfo.MagicQuery[:], binCert[104:112])
|
||||
if isNew {
|
||||
dlog.Noticef("[%s] OK (crypto v%d) - rtt: %dms", *serverName, cryptoConstruction, rtt.Nanoseconds()/1000000)
|
||||
} else {
|
||||
dlog.Infof("[%s] OK (crypto v%d) - rtt: %dms", *serverName, cryptoConstruction, rtt.Nanoseconds()/1000000)
|
||||
}
|
||||
}
|
||||
if certInfo.CryptoConstruction == UndefinedConstruction {
|
||||
return certInfo, 0, errors.New("No useable certificate found")
|
||||
}
|
||||
return certInfo, int(rtt.Nanoseconds() / 1000000), nil
|
||||
}
|
||||
|
||||
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
||||
|
||||
func dddToByte(s []byte) byte {
|
||||
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||
}
|
||||
|
||||
func packTxtString(s string) ([]byte, error) {
|
||||
bs := make([]byte, len(s))
|
||||
msg := make([]byte, 0)
|
||||
copy(bs, s)
|
||||
for i := 0; i < len(bs); i++ {
|
||||
if bs[i] == '\\' {
|
||||
i++
|
||||
if i == len(bs) {
|
||||
break
|
||||
}
|
||||
if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
|
||||
msg = append(msg, dddToByte(bs[i:]))
|
||||
i += 2
|
||||
} else if bs[i] == 't' {
|
||||
msg = append(msg, '\t')
|
||||
} else if bs[i] == 'r' {
|
||||
msg = append(msg, '\r')
|
||||
} else if bs[i] == 'n' {
|
||||
msg = append(msg, '\n')
|
||||
} else {
|
||||
msg = append(msg, bs[i])
|
||||
}
|
||||
} else {
|
||||
msg = append(msg, bs[i])
|
||||
}
|
||||
}
|
||||
return msg, nil
|
||||
}
|
|
@ -271,7 +271,22 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto str
|
|||
}
|
||||
if len(response) == 0 {
|
||||
var ttl *uint32
|
||||
if serverInfo.Proto == StampProtoTypeDoH {
|
||||
if serverInfo.Proto == StampProtoTypeDNSCrypt {
|
||||
encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
serverInfo.noticeBegin(proxy)
|
||||
if serverProto == "udp" {
|
||||
response, err = proxy.exchangeWithUDPServer(serverInfo, encryptedQuery, clientNonce)
|
||||
} else {
|
||||
response, err = proxy.exchangeWithTCPServer(serverInfo, encryptedQuery, clientNonce)
|
||||
}
|
||||
if err != nil {
|
||||
serverInfo.noticeFailure(proxy)
|
||||
return
|
||||
}
|
||||
} else if serverInfo.Proto == StampProtoTypeDoH {
|
||||
tid := TransactionID(query)
|
||||
SetTransactionID(query, 0)
|
||||
serverInfo.noticeBegin(proxy)
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -16,6 +17,7 @@ import (
|
|||
|
||||
"github.com/VividCortex/ewma"
|
||||
"github.com/jedisct1/dlog"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -205,12 +207,49 @@ func (serversInfo *ServersInfo) getOne() *ServerInfo {
|
|||
}
|
||||
|
||||
func (serversInfo *ServersInfo) fetchServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) {
|
||||
if stamp.proto == StampProtoTypeDoH {
|
||||
if stamp.proto == StampProtoTypeDNSCrypt {
|
||||
return serversInfo.fetchDNSCryptServerInfo(proxy, name, stamp, isNew)
|
||||
} else if stamp.proto == StampProtoTypeDoH {
|
||||
return serversInfo.fetchDoHServerInfo(proxy, name, stamp, isNew)
|
||||
}
|
||||
return ServerInfo{}, errors.New("Unsupported protocol")
|
||||
}
|
||||
|
||||
func (serversInfo *ServersInfo) fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) {
|
||||
if len(stamp.serverPk) != ed25519.PublicKeySize {
|
||||
serverPk, err := hex.DecodeString(strings.Replace(string(stamp.serverPk), ":", "", -1))
|
||||
if err != nil || len(serverPk) != ed25519.PublicKeySize {
|
||||
dlog.Fatalf("Unsupported public key for [%s]: [%s]", name, stamp.serverPk)
|
||||
}
|
||||
dlog.Warnf("Public key [%s] shouldn't be hex-encoded any more", string(stamp.serverPk))
|
||||
stamp.serverPk = serverPk
|
||||
}
|
||||
certInfo, rtt, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.serverPk, stamp.serverAddrStr, stamp.providerName, isNew)
|
||||
if err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
remoteUDPAddr, err := net.ResolveUDPAddr("udp", stamp.serverAddrStr)
|
||||
if err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
remoteTCPAddr, err := net.ResolveTCPAddr("tcp", stamp.serverAddrStr)
|
||||
if err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
return ServerInfo{
|
||||
Proto: StampProtoTypeDNSCrypt,
|
||||
MagicQuery: certInfo.MagicQuery,
|
||||
ServerPk: certInfo.ServerPk,
|
||||
SharedKey: certInfo.SharedKey,
|
||||
CryptoConstruction: certInfo.CryptoConstruction,
|
||||
Name: name,
|
||||
Timeout: proxy.timeout,
|
||||
UDPAddr: remoteUDPAddr,
|
||||
TCPAddr: remoteTCPAddr,
|
||||
initialRtt: rtt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) {
|
||||
if len(stamp.serverAddrStr) > 0 {
|
||||
addrStr := stamp.serverAddrStr
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -208,13 +209,58 @@ func NewSource(xTransport *XTransport, urls []string, minisignKeyStr string, cac
|
|||
}
|
||||
|
||||
func (source *Source) Parse(prefix string) ([]RegisteredServer, error) {
|
||||
if source.format == SourceFormatV2 {
|
||||
if source.format == SourceFormatV1 {
|
||||
return source.parseV1(prefix)
|
||||
} else if source.format == SourceFormatV2 {
|
||||
return source.parseV2(prefix)
|
||||
}
|
||||
dlog.Fatal("Unexpected source format")
|
||||
return []RegisteredServer{}, nil
|
||||
}
|
||||
|
||||
func (source *Source) parseV1(prefix string) ([]RegisteredServer, error) {
|
||||
var registeredServers []RegisteredServer
|
||||
|
||||
csvReader := csv.NewReader(strings.NewReader(source.in))
|
||||
records, err := csvReader.ReadAll()
|
||||
if err != nil {
|
||||
return registeredServers, nil
|
||||
}
|
||||
for lineNo, record := range records {
|
||||
if len(record) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(record) < 14 {
|
||||
return registeredServers, fmt.Errorf("Parse error at line %d", 1+lineNo)
|
||||
}
|
||||
if lineNo == 0 {
|
||||
continue
|
||||
}
|
||||
name := prefix + record[0]
|
||||
description := record[2]
|
||||
serverAddrStr := record[10]
|
||||
providerName := record[11]
|
||||
serverPkStr := record[12]
|
||||
props := ServerInformalProperties(0)
|
||||
if strings.EqualFold(record[7], "yes") {
|
||||
props |= ServerInformalPropertyDNSSEC
|
||||
}
|
||||
if strings.EqualFold(record[8], "yes") {
|
||||
props |= ServerInformalPropertyNoLog
|
||||
}
|
||||
stamp, err := NewDNSCryptServerStampFromLegacy(serverAddrStr, serverPkStr, providerName, props)
|
||||
if err != nil {
|
||||
return registeredServers, err
|
||||
}
|
||||
registeredServer := RegisteredServer{
|
||||
name: name, stamp: stamp, description: description,
|
||||
}
|
||||
dlog.Debugf("Registered [%s] with stamp [%s]", name, stamp.String())
|
||||
registeredServers = append(registeredServers, registeredServer)
|
||||
}
|
||||
return registeredServers, nil
|
||||
}
|
||||
|
||||
func (source *Source) parseV2(prefix string) ([]RegisteredServer, error) {
|
||||
var registeredServers []RegisteredServer
|
||||
in := string(source.in)
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -10,19 +11,23 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/jedisct1/dlog"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
type StampProtoType uint8
|
||||
|
||||
const (
|
||||
StampProtoTypePlain = StampProtoType(0x00)
|
||||
StampProtoTypeDoH = StampProtoType(0x02)
|
||||
StampProtoTypePlain = StampProtoType(0x00)
|
||||
StampProtoTypeDNSCrypt = StampProtoType(0x01)
|
||||
StampProtoTypeDoH = StampProtoType(0x02)
|
||||
)
|
||||
|
||||
func (stampProtoType *StampProtoType) String() string {
|
||||
switch *stampProtoType {
|
||||
case StampProtoTypePlain:
|
||||
return "Plain"
|
||||
case StampProtoTypeDNSCrypt:
|
||||
return "DNSCrypt"
|
||||
case StampProtoTypeDoH:
|
||||
return "DoH"
|
||||
default:
|
||||
|
@ -40,6 +45,23 @@ type ServerStamp struct {
|
|||
proto StampProtoType
|
||||
}
|
||||
|
||||
func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) {
|
||||
if net.ParseIP(serverAddrStr) != nil {
|
||||
serverAddrStr = fmt.Sprintf("%s:%d", serverAddrStr, DefaultPort)
|
||||
}
|
||||
serverPk, err := hex.DecodeString(strings.Replace(serverPkStr, ":", "", -1))
|
||||
if err != nil || len(serverPk) != ed25519.PublicKeySize {
|
||||
return ServerStamp{}, fmt.Errorf("Unsupported public key: [%s]", serverPkStr)
|
||||
}
|
||||
return ServerStamp{
|
||||
serverAddrStr: serverAddrStr,
|
||||
serverPk: serverPk,
|
||||
providerName: providerName,
|
||||
props: props,
|
||||
proto: StampProtoTypeDNSCrypt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewServerStampFromString(stampStr string) (ServerStamp, error) {
|
||||
if !strings.HasPrefix(stampStr, "sdns://") && !strings.HasPrefix(stampStr, "dnsc://") {
|
||||
return ServerStamp{}, errors.New("Stamps are expected to start with sdns://")
|
||||
|
@ -51,12 +73,58 @@ func NewServerStampFromString(stampStr string) (ServerStamp, error) {
|
|||
if len(bin) < 1 {
|
||||
return ServerStamp{}, errors.New("Stamp is too short")
|
||||
}
|
||||
if bin[0] == uint8(StampProtoTypeDoH) {
|
||||
if bin[0] == uint8(StampProtoTypeDNSCrypt) {
|
||||
return newDNSCryptServerStamp(bin)
|
||||
} else if bin[0] == uint8(StampProtoTypeDoH) {
|
||||
return newDoHServerStamp(bin)
|
||||
}
|
||||
return ServerStamp{}, errors.New("Unsupported stamp version or protocol")
|
||||
}
|
||||
|
||||
// id(u8)=0x01 props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName
|
||||
|
||||
func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
|
||||
stamp := ServerStamp{proto: StampProtoTypeDNSCrypt}
|
||||
if len(bin) < 66 {
|
||||
return stamp, errors.New("Stamp is too short")
|
||||
}
|
||||
stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
|
||||
binLen := len(bin)
|
||||
pos := 9
|
||||
|
||||
len := int(bin[pos])
|
||||
if 1+len >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.serverAddrStr = string(bin[pos : pos+len])
|
||||
pos += len
|
||||
if net.ParseIP(strings.TrimRight(strings.TrimLeft(stamp.serverAddrStr, "["), "]")) != nil {
|
||||
stamp.serverAddrStr = fmt.Sprintf("%s:%d", stamp.serverAddrStr, DefaultPort)
|
||||
}
|
||||
|
||||
len = int(bin[pos])
|
||||
if 1+len >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.serverPk = bin[pos : pos+len]
|
||||
pos += len
|
||||
|
||||
len = int(bin[pos])
|
||||
if len >= binLen-pos {
|
||||
return stamp, errors.New("Invalid stamp")
|
||||
}
|
||||
pos++
|
||||
stamp.providerName = string(bin[pos : pos+len])
|
||||
pos += len
|
||||
|
||||
if pos != binLen {
|
||||
return stamp, errors.New("Invalid stamp (garbage after end)")
|
||||
}
|
||||
return stamp, nil
|
||||
}
|
||||
|
||||
// id(u8)=0x02 props addrLen(1) serverAddr hashLen(1) hash providerNameLen(1) providerName pathLen(1) path
|
||||
|
||||
func newDoHServerStamp(bin []byte) (ServerStamp, error) {
|
||||
|
@ -120,13 +188,38 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
|
|||
}
|
||||
|
||||
func (stamp *ServerStamp) String() string {
|
||||
if stamp.proto == StampProtoTypeDoH {
|
||||
if stamp.proto == StampProtoTypeDNSCrypt {
|
||||
return stamp.dnsCryptString()
|
||||
} else if stamp.proto == StampProtoTypeDoH {
|
||||
return stamp.dohString()
|
||||
}
|
||||
dlog.Fatal("Unsupported protocol")
|
||||
return ""
|
||||
}
|
||||
|
||||
func (stamp *ServerStamp) dnsCryptString() string {
|
||||
bin := make([]uint8, 9)
|
||||
bin[0] = uint8(StampProtoTypeDNSCrypt)
|
||||
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props))
|
||||
|
||||
serverAddrStr := stamp.serverAddrStr
|
||||
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) {
|
||||
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))]
|
||||
}
|
||||
bin = append(bin, uint8(len(serverAddrStr)))
|
||||
bin = append(bin, []uint8(serverAddrStr)...)
|
||||
|
||||
bin = append(bin, uint8(len(stamp.serverPk)))
|
||||
bin = append(bin, stamp.serverPk...)
|
||||
|
||||
bin = append(bin, uint8(len(stamp.providerName)))
|
||||
bin = append(bin, []uint8(stamp.providerName)...)
|
||||
|
||||
str := base64.RawURLEncoding.EncodeToString(bin)
|
||||
|
||||
return "sdns://" + str
|
||||
}
|
||||
|
||||
func (stamp *ServerStamp) dohString() string {
|
||||
bin := make([]uint8, 9)
|
||||
bin[0] = uint8(StampProtoTypeDoH)
|
||||
|
|
Loading…
Reference in New Issue