Split stamps into package

This commit is contained in:
gdm85 2018-04-14 15:03:21 +02:00 committed by Frank Denis
parent e49ce4f12b
commit eb5f391fa6
6 changed files with 113 additions and 107 deletions

View File

@ -13,6 +13,7 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/jedisct1/dlog" "github.com/jedisct1/dlog"
"github.com/jedisct1/dnscrypt-proxy/stamps"
) )
type Config struct { type Config struct {
@ -380,11 +381,11 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error {
func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) { func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) {
var summary []ServerSummary var summary []ServerSummary
for _, registeredServer := range proxy.registeredServers { for _, registeredServer := range proxy.registeredServers {
addrStr, port := registeredServer.stamp.serverAddrStr, DefaultPort addrStr, port := registeredServer.stamp.ServerAddrStr, stamps.DefaultPort
port = ExtractPort(addrStr, port) port = ExtractPort(addrStr, port)
addrs := make([]string, 0) addrs := make([]string, 0)
if registeredServer.stamp.proto == StampProtoTypeDoH && len(registeredServer.stamp.providerName) > 0 { if registeredServer.stamp.Proto == stamps.StampProtoTypeDoH && len(registeredServer.stamp.ProviderName) > 0 {
providerName := registeredServer.stamp.providerName providerName := registeredServer.stamp.ProviderName
var host string var host string
host, port = ExtractHostAndPort(providerName, port) host, port = ExtractHostAndPort(providerName, port)
addrs = append(addrs, host) addrs = append(addrs, host)
@ -394,13 +395,13 @@ func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) {
} }
serverSummary := ServerSummary{ serverSummary := ServerSummary{
Name: registeredServer.name, Name: registeredServer.name,
Proto: registeredServer.stamp.proto.String(), Proto: registeredServer.stamp.Proto.String(),
IPv6: strings.HasPrefix(addrStr, "["), IPv6: strings.HasPrefix(addrStr, "["),
Ports: []int{port}, Ports: []int{port},
Addrs: addrs, Addrs: addrs,
DNSSEC: registeredServer.stamp.props&ServerInformalPropertyDNSSEC != 0, DNSSEC: registeredServer.stamp.Props&stamps.ServerInformalPropertyDNSSEC != 0,
NoLog: registeredServer.stamp.props&ServerInformalPropertyNoLog != 0, NoLog: registeredServer.stamp.Props&stamps.ServerInformalPropertyNoLog != 0,
NoFilter: registeredServer.stamp.props&ServerInformalPropertyNoFilter != 0, NoFilter: registeredServer.stamp.Props&stamps.ServerInformalPropertyNoFilter != 0,
Description: registeredServer.description, Description: registeredServer.description,
} }
if jsonOutput { if jsonOutput {
@ -419,15 +420,15 @@ func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) {
} }
func (config *Config) loadSources(proxy *Proxy) error { func (config *Config) loadSources(proxy *Proxy) error {
requiredProps := ServerInformalProperties(0) var requiredProps stamps.ServerInformalProperties
if config.SourceRequireDNSSEC { if config.SourceRequireDNSSEC {
requiredProps |= ServerInformalPropertyDNSSEC requiredProps |= stamps.ServerInformalPropertyDNSSEC
} }
if config.SourceRequireNoLog { if config.SourceRequireNoLog {
requiredProps |= ServerInformalPropertyNoLog requiredProps |= stamps.ServerInformalPropertyNoLog
} }
if config.SourceRequireNoFilter { if config.SourceRequireNoFilter {
requiredProps |= ServerInformalPropertyNoFilter requiredProps |= stamps.ServerInformalPropertyNoFilter
} }
for cfgSourceName, cfgSource := range config.SourcesConfig { for cfgSourceName, cfgSource := range config.SourcesConfig {
if err := config.loadSource(proxy, requiredProps, cfgSourceName, &cfgSource); err != nil { if err := config.loadSource(proxy, requiredProps, cfgSourceName, &cfgSource); err != nil {
@ -447,7 +448,7 @@ func (config *Config) loadSources(proxy *Proxy) error {
if len(staticConfig.Stamp) == 0 { if len(staticConfig.Stamp) == 0 {
dlog.Fatalf("Missing stamp for the static [%s] definition", serverName) dlog.Fatalf("Missing stamp for the static [%s] definition", serverName)
} }
stamp, err := NewServerStampFromString(staticConfig.Stamp) stamp, err := stamps.NewServerStampFromString(staticConfig.Stamp)
if err != nil { if err != nil {
return err return err
} }
@ -456,7 +457,7 @@ func (config *Config) loadSources(proxy *Proxy) error {
return nil return nil
} }
func (config *Config) loadSource(proxy *Proxy, requiredProps ServerInformalProperties, cfgSourceName string, cfgSource *SourceConfig) error { func (config *Config) loadSource(proxy *Proxy, requiredProps stamps.ServerInformalProperties, cfgSourceName string, cfgSource *SourceConfig) error {
if len(cfgSource.URLs) == 0 { if len(cfgSource.URLs) == 0 {
if len(cfgSource.URL) == 0 { if len(cfgSource.URL) == 0 {
dlog.Debugf("Missing URLs for source [%s]", cfgSourceName) dlog.Debugf("Missing URLs for source [%s]", cfgSourceName)
@ -492,23 +493,23 @@ func (config *Config) loadSource(proxy *Proxy, requiredProps ServerInformalPrope
if !includesName(config.ServerNames, registeredServer.name) { if !includesName(config.ServerNames, registeredServer.name) {
continue continue
} }
} else if registeredServer.stamp.props&requiredProps != requiredProps { } else if registeredServer.stamp.Props&requiredProps != requiredProps {
continue continue
} }
if config.SourceIPv4 || config.SourceIPv6 { if config.SourceIPv4 || config.SourceIPv6 {
isIPv4, isIPv6 := true, false isIPv4, isIPv6 := true, false
if registeredServer.stamp.proto == StampProtoTypeDoH { if registeredServer.stamp.Proto == stamps.StampProtoTypeDoH {
isIPv4, isIPv6 = true, true isIPv4, isIPv6 = true, true
} }
if strings.HasPrefix(registeredServer.stamp.serverAddrStr, "[") { if strings.HasPrefix(registeredServer.stamp.ServerAddrStr, "[") {
isIPv4, isIPv6 = false, true isIPv4, isIPv6 = false, true
} }
if !(config.SourceIPv4 == isIPv4 || config.SourceIPv6 == isIPv6) { if !(config.SourceIPv4 == isIPv4 || config.SourceIPv6 == isIPv6) {
continue continue
} }
} }
if !((config.SourceDNSCrypt && registeredServer.stamp.proto == StampProtoTypeDNSCrypt) || if !((config.SourceDNSCrypt && registeredServer.stamp.Proto == stamps.StampProtoTypeDNSCrypt) ||
(config.SourceDoH && registeredServer.stamp.proto == StampProtoTypeDoH)) { (config.SourceDoH && registeredServer.stamp.Proto == stamps.StampProtoTypeDoH)) {
continue continue
} }
dlog.Debugf("Adding [%s] to the set of wanted resolvers", registeredServer.name) dlog.Debugf("Adding [%s] to the set of wanted resolvers", registeredServer.name)

View File

@ -11,6 +11,7 @@ import (
"github.com/jedisct1/dlog" "github.com/jedisct1/dlog"
clocksmith "github.com/jedisct1/go-clocksmith" clocksmith "github.com/jedisct1/go-clocksmith"
"golang.org/x/crypto/curve25519" "golang.org/x/crypto/curve25519"
"github.com/jedisct1/dnscrypt-proxy/stamps"
) )
type Proxy struct { type Proxy struct {
@ -274,7 +275,7 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto str
} }
if len(response) == 0 { if len(response) == 0 {
var ttl *uint32 var ttl *uint32
if serverInfo.Proto == StampProtoTypeDNSCrypt { if serverInfo.Proto == stamps.StampProtoTypeDNSCrypt {
sharedKey, encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto) sharedKey, encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
if err != nil { if err != nil {
return return
@ -289,7 +290,7 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto str
serverInfo.noticeFailure(proxy) serverInfo.noticeFailure(proxy)
return return
} }
} else if serverInfo.Proto == StampProtoTypeDoH { } else if serverInfo.Proto == stamps.StampProtoTypeDoH {
tid := TransactionID(query) tid := TransactionID(query)
SetTransactionID(query, 0) SetTransactionID(query, 0)
serverInfo.noticeBegin(proxy) serverInfo.noticeBegin(proxy)

View File

@ -17,31 +17,23 @@ import (
"github.com/VividCortex/ewma" "github.com/VividCortex/ewma"
"github.com/jedisct1/dlog" "github.com/jedisct1/dlog"
"github.com/jedisct1/dnscrypt-proxy/stamps"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
) )
const ( const (
RTTEwmaDecay = 10.0 RTTEwmaDecay = 10.0
DefaultPort = 443
)
type ServerInformalProperties uint64
const (
ServerInformalPropertyDNSSEC = ServerInformalProperties(1) << 0
ServerInformalPropertyNoLog = ServerInformalProperties(1) << 1
ServerInformalPropertyNoFilter = ServerInformalProperties(1) << 2
) )
type RegisteredServer struct { type RegisteredServer struct {
name string name string
stamp ServerStamp stamp stamps.ServerStamp
description string description string
} }
type ServerInfo struct { type ServerInfo struct {
sync.RWMutex sync.RWMutex
Proto StampProtoType Proto stamps.StampProtoType
MagicQuery [8]byte MagicQuery [8]byte
ServerPk [32]byte ServerPk [32]byte
SharedKey [32]byte SharedKey [32]byte
@ -77,7 +69,7 @@ type ServersInfo struct {
lbStrategy LBStrategy lbStrategy LBStrategy
} }
func (serversInfo *ServersInfo) registerServer(proxy *Proxy, name string, stamp ServerStamp) error { func (serversInfo *ServersInfo) registerServer(proxy *Proxy, name string, stamp stamps.ServerStamp) error {
newRegisteredServer := RegisteredServer{name: name, stamp: stamp} newRegisteredServer := RegisteredServer{name: name, stamp: stamp}
serversInfo.Lock() serversInfo.Lock()
defer serversInfo.Unlock() defer serversInfo.Unlock()
@ -91,7 +83,7 @@ func (serversInfo *ServersInfo) registerServer(proxy *Proxy, name string, stamp
return nil return nil
} }
func (serversInfo *ServersInfo) refreshServer(proxy *Proxy, name string, stamp ServerStamp) error { func (serversInfo *ServersInfo) refreshServer(proxy *Proxy, name string, stamp stamps.ServerStamp) error {
serversInfo.Lock() serversInfo.Lock()
defer serversInfo.Unlock() defer serversInfo.Unlock()
previousIndex := -1 previousIndex := -1
@ -206,38 +198,38 @@ func (serversInfo *ServersInfo) getOne() *ServerInfo {
return serverInfo return serverInfo
} }
func (serversInfo *ServersInfo) fetchServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) { func (serversInfo *ServersInfo) fetchServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) {
if stamp.proto == StampProtoTypeDNSCrypt { if stamp.Proto == stamps.StampProtoTypeDNSCrypt {
return serversInfo.fetchDNSCryptServerInfo(proxy, name, stamp, isNew) return serversInfo.fetchDNSCryptServerInfo(proxy, name, stamp, isNew)
} else if stamp.proto == StampProtoTypeDoH { } else if stamp.Proto == stamps.StampProtoTypeDoH {
return serversInfo.fetchDoHServerInfo(proxy, name, stamp, isNew) return serversInfo.fetchDoHServerInfo(proxy, name, stamp, isNew)
} }
return ServerInfo{}, errors.New("Unsupported protocol") return ServerInfo{}, errors.New("Unsupported protocol")
} }
func (serversInfo *ServersInfo) fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) { func (serversInfo *ServersInfo) fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) {
if len(stamp.serverPk) != ed25519.PublicKeySize { if len(stamp.ServerPk) != ed25519.PublicKeySize {
serverPk, err := hex.DecodeString(strings.Replace(string(stamp.serverPk), ":", "", -1)) serverPk, err := hex.DecodeString(strings.Replace(string(stamp.ServerPk), ":", "", -1))
if err != nil || len(serverPk) != ed25519.PublicKeySize { if err != nil || len(serverPk) != ed25519.PublicKeySize {
dlog.Fatalf("Unsupported public key for [%s]: [%s]", name, stamp.serverPk) 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)) dlog.Warnf("Public key [%s] shouldn't be hex-encoded any more", string(stamp.ServerPk))
stamp.serverPk = serverPk stamp.ServerPk = serverPk
} }
certInfo, rtt, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.serverPk, stamp.serverAddrStr, stamp.providerName, isNew) certInfo, rtt, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.ServerPk, stamp.ServerAddrStr, stamp.ProviderName, isNew)
if err != nil { if err != nil {
return ServerInfo{}, err return ServerInfo{}, err
} }
remoteUDPAddr, err := net.ResolveUDPAddr("udp", stamp.serverAddrStr) remoteUDPAddr, err := net.ResolveUDPAddr("udp", stamp.ServerAddrStr)
if err != nil { if err != nil {
return ServerInfo{}, err return ServerInfo{}, err
} }
remoteTCPAddr, err := net.ResolveTCPAddr("tcp", stamp.serverAddrStr) remoteTCPAddr, err := net.ResolveTCPAddr("tcp", stamp.ServerAddrStr)
if err != nil { if err != nil {
return ServerInfo{}, err return ServerInfo{}, err
} }
return ServerInfo{ return ServerInfo{
Proto: StampProtoTypeDNSCrypt, Proto: stamps.StampProtoTypeDNSCrypt,
MagicQuery: certInfo.MagicQuery, MagicQuery: certInfo.MagicQuery,
ServerPk: certInfo.ServerPk, ServerPk: certInfo.ServerPk,
SharedKey: certInfo.SharedKey, SharedKey: certInfo.SharedKey,
@ -250,18 +242,18 @@ func (serversInfo *ServersInfo) fetchDNSCryptServerInfo(proxy *Proxy, name strin
}, nil }, nil
} }
func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, stamp ServerStamp, isNew bool) (ServerInfo, error) { func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) {
if len(stamp.serverAddrStr) > 0 { if len(stamp.ServerAddrStr) > 0 {
addrStr := stamp.serverAddrStr addrStr := stamp.ServerAddrStr
ipOnly := addrStr[:strings.LastIndex(addrStr, ":")] ipOnly := addrStr[:strings.LastIndex(addrStr, ":")]
proxy.xTransport.cachedIPs.Lock() proxy.xTransport.cachedIPs.Lock()
proxy.xTransport.cachedIPs.cache[stamp.providerName] = ipOnly proxy.xTransport.cachedIPs.cache[stamp.ProviderName] = ipOnly
proxy.xTransport.cachedIPs.Unlock() proxy.xTransport.cachedIPs.Unlock()
} }
url := &url.URL{ url := &url.URL{
Scheme: "https", Scheme: "https",
Host: stamp.providerName, Host: stamp.ProviderName,
Path: stamp.path, Path: stamp.Path,
} }
body := []byte{ body := []byte{
0xca, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xca, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
@ -293,7 +285,7 @@ func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, st
} else { } else {
dlog.Debugf("Advertised cert: [%s] [%x]", cert.Subject, h) dlog.Debugf("Advertised cert: [%s] [%x]", cert.Subject, h)
} }
for _, hash := range stamp.hashes { for _, hash := range stamp.Hashes {
if len(hash) == len(wantedHash) { if len(hash) == len(wantedHash) {
copy(wantedHash[:], hash) copy(wantedHash[:], hash)
if h == wantedHash { if h == wantedHash {
@ -306,7 +298,7 @@ func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, st
break break
} }
} }
if !found && len(stamp.hashes) > 0 { if !found && len(stamp.Hashes) > 0 {
return ServerInfo{}, fmt.Errorf("Certificate hash [%x] not found for [%s]", wantedHash, name) return ServerInfo{}, fmt.Errorf("Certificate hash [%x] not found for [%s]", wantedHash, name)
} }
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, MaxHTTPBodyLength)) respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, MaxHTTPBodyLength))
@ -323,11 +315,11 @@ func (serversInfo *ServersInfo) fetchDoHServerInfo(proxy *Proxy, name string, st
dlog.Infof("[%s] OK (DoH) - rtt: %dms", name, rtt.Nanoseconds()/1000000) dlog.Infof("[%s] OK (DoH) - rtt: %dms", name, rtt.Nanoseconds()/1000000)
} }
return ServerInfo{ return ServerInfo{
Proto: StampProtoTypeDoH, Proto: stamps.StampProtoTypeDoH,
Name: name, Name: name,
Timeout: proxy.timeout, Timeout: proxy.timeout,
URL: url, URL: url,
HostName: stamp.providerName, HostName: stamp.ProviderName,
initialRtt: int(rtt.Nanoseconds() / 1000000), initialRtt: int(rtt.Nanoseconds() / 1000000),
useGet: useGet, useGet: useGet,
}, nil }, nil

View File

@ -18,6 +18,7 @@ import (
"github.com/jedisct1/dlog" "github.com/jedisct1/dlog"
"github.com/jedisct1/go-minisign" "github.com/jedisct1/go-minisign"
"github.com/jedisct1/dnscrypt-proxy/stamps"
) )
type SourceFormat int type SourceFormat int
@ -241,14 +242,14 @@ func (source *Source) parseV1(prefix string) ([]RegisteredServer, error) {
serverAddrStr := record[10] serverAddrStr := record[10]
providerName := record[11] providerName := record[11]
serverPkStr := record[12] serverPkStr := record[12]
props := ServerInformalProperties(0) props := stamps.ServerInformalProperties(0)
if strings.EqualFold(record[7], "yes") { if strings.EqualFold(record[7], "yes") {
props |= ServerInformalPropertyDNSSEC props |= stamps.ServerInformalPropertyDNSSEC
} }
if strings.EqualFold(record[8], "yes") { if strings.EqualFold(record[8], "yes") {
props |= ServerInformalPropertyNoLog props |= stamps.ServerInformalPropertyNoLog
} }
stamp, err := NewDNSCryptServerStampFromLegacy(serverAddrStr, serverPkStr, providerName, props) stamp, err := stamps.NewDNSCryptServerStampFromLegacy(serverAddrStr, serverPkStr, providerName, props)
if err != nil { if err != nil {
return registeredServers, err return registeredServers, err
} }
@ -301,7 +302,7 @@ func (source *Source) parseV2(prefix string) ([]RegisteredServer, error) {
if len(stampStr) < 8 { if len(stampStr) < 8 {
return registeredServers, fmt.Errorf("Missing stamp for server [%s] in source from [%v]", name, source.urls) return registeredServers, fmt.Errorf("Missing stamp for server [%s] in source from [%v]", name, source.urls)
} }
stamp, err := NewServerStampFromString(stampStr) stamp, err := stamps.NewServerStampFromString(stampStr)
if err != nil { if err != nil {
return registeredServers, err return registeredServers, err
} }

View File

@ -16,7 +16,8 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/jedisct1/dnscrypt-proxy/stamps"
"github.com/jedisct1/dlog" "github.com/jedisct1/dlog"
"github.com/miekg/dns" "github.com/miekg/dns"
"golang.org/x/net/http2" "golang.org/x/net/http2"
@ -83,7 +84,7 @@ func (xTransport *XTransport) rebuildTransport() {
ExpectContinueTimeout: timeout, ExpectContinueTimeout: timeout,
MaxResponseHeaderBytes: 4096, MaxResponseHeaderBytes: 4096,
DialContext: func(ctx context.Context, network, addrStr string) (net.Conn, error) { DialContext: func(ctx context.Context, network, addrStr string) (net.Conn, error) {
host, port := ExtractHostAndPort(addrStr, DefaultPort) host, port := ExtractHostAndPort(addrStr, stamps.DefaultPort)
ipOnly := host ipOnly := host
xTransport.cachedIPs.RLock() xTransport.cachedIPs.RLock()
cachedIP := xTransport.cachedIPs.cache[host] cachedIP := xTransport.cachedIPs.cache[host]

View File

@ -1,4 +1,4 @@
package main package stamps
import ( import (
"encoding/base64" "encoding/base64"
@ -14,6 +14,16 @@ import (
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
) )
const DefaultPort = 443
type ServerInformalProperties uint64
const (
ServerInformalPropertyDNSSEC = ServerInformalProperties(1) << 0
ServerInformalPropertyNoLog = ServerInformalProperties(1) << 1
ServerInformalPropertyNoFilter = ServerInformalProperties(1) << 2
)
type StampProtoType uint8 type StampProtoType uint8
const ( const (
@ -36,13 +46,13 @@ func (stampProtoType *StampProtoType) String() string {
} }
type ServerStamp struct { type ServerStamp struct {
serverAddrStr string ServerAddrStr string
serverPk []uint8 ServerPk []uint8
hashes [][]uint8 Hashes [][]uint8
providerName string ProviderName string
path string Path string
props ServerInformalProperties Props ServerInformalProperties
proto StampProtoType Proto StampProtoType
} }
func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) { func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) {
@ -54,11 +64,11 @@ func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string,
return ServerStamp{}, fmt.Errorf("Unsupported public key: [%s]", serverPkStr) return ServerStamp{}, fmt.Errorf("Unsupported public key: [%s]", serverPkStr)
} }
return ServerStamp{ return ServerStamp{
serverAddrStr: serverAddrStr, ServerAddrStr: serverAddrStr,
serverPk: serverPk, ServerPk: serverPk,
providerName: providerName, ProviderName: providerName,
props: props, Props: props,
proto: StampProtoTypeDNSCrypt, Proto: StampProtoTypeDNSCrypt,
}, nil }, nil
} }
@ -84,11 +94,11 @@ func NewServerStampFromString(stampStr string) (ServerStamp, error) {
// id(u8)=0x01 props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName // id(u8)=0x01 props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName
func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) { func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{proto: StampProtoTypeDNSCrypt} stamp := ServerStamp{Proto: StampProtoTypeDNSCrypt}
if len(bin) < 66 { if len(bin) < 66 {
return stamp, errors.New("Stamp is too short") return stamp, errors.New("Stamp is too short")
} }
stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9])) stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin) binLen := len(bin)
pos := 9 pos := 9
@ -97,10 +107,10 @@ func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.serverAddrStr = string(bin[pos : pos+len]) stamp.ServerAddrStr = string(bin[pos : pos+len])
pos += len pos += len
if net.ParseIP(strings.TrimRight(strings.TrimLeft(stamp.serverAddrStr, "["), "]")) != nil { if net.ParseIP(strings.TrimRight(strings.TrimLeft(stamp.ServerAddrStr, "["), "]")) != nil {
stamp.serverAddrStr = fmt.Sprintf("%s:%d", stamp.serverAddrStr, DefaultPort) stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
} }
len = int(bin[pos]) len = int(bin[pos])
@ -108,7 +118,7 @@ func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.serverPk = bin[pos : pos+len] stamp.ServerPk = bin[pos : pos+len]
pos += len pos += len
len = int(bin[pos]) len = int(bin[pos])
@ -116,7 +126,7 @@ func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.providerName = string(bin[pos : pos+len]) stamp.ProviderName = string(bin[pos : pos+len])
pos += len pos += len
if pos != binLen { if pos != binLen {
@ -128,11 +138,11 @@ func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
// id(u8)=0x02 props addrLen(1) serverAddr hashLen(1) hash providerNameLen(1) providerName pathLen(1) path // id(u8)=0x02 props addrLen(1) serverAddr hashLen(1) hash providerNameLen(1) providerName pathLen(1) path
func newDoHServerStamp(bin []byte) (ServerStamp, error) { func newDoHServerStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{proto: StampProtoTypeDoH, hashes: [][]byte{}} stamp := ServerStamp{Proto: StampProtoTypeDoH}
if len(bin) < 22 { if len(bin) < 22 {
return stamp, errors.New("Stamp is too short") return stamp, errors.New("Stamp is too short")
} }
stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9])) stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin) binLen := len(bin)
pos := 9 pos := 9
@ -141,7 +151,7 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.serverAddrStr = string(bin[pos : pos+len]) stamp.ServerAddrStr = string(bin[pos : pos+len])
pos += len pos += len
for { for {
@ -152,7 +162,7 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
} }
pos++ pos++
if len > 0 { if len > 0 {
stamp.hashes = append(stamp.hashes, bin[pos:pos+len]) stamp.Hashes = append(stamp.Hashes, bin[pos:pos+len])
} }
pos += len pos += len
if vlen&0x80 != 0x80 { if vlen&0x80 != 0x80 {
@ -165,7 +175,7 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.providerName = string(bin[pos : pos+len]) stamp.ProviderName = string(bin[pos : pos+len])
pos += len pos += len
len = int(bin[pos]) len = int(bin[pos])
@ -173,24 +183,24 @@ func newDoHServerStamp(bin []byte) (ServerStamp, error) {
return stamp, errors.New("Invalid stamp") return stamp, errors.New("Invalid stamp")
} }
pos++ pos++
stamp.path = string(bin[pos : pos+len]) stamp.Path = string(bin[pos : pos+len])
pos += len pos += len
if pos != binLen { if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)") return stamp, errors.New("Invalid stamp (garbage after end)")
} }
if net.ParseIP(strings.TrimRight(strings.TrimLeft(stamp.serverAddrStr, "["), "]")) != nil { if net.ParseIP(strings.TrimRight(strings.TrimLeft(stamp.ServerAddrStr, "["), "]")) != nil {
stamp.serverAddrStr = fmt.Sprintf("%s:%d", stamp.serverAddrStr, DefaultPort) stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
} }
return stamp, nil return stamp, nil
} }
func (stamp *ServerStamp) String() string { func (stamp *ServerStamp) String() string {
if stamp.proto == StampProtoTypeDNSCrypt { if stamp.Proto == StampProtoTypeDNSCrypt {
return stamp.dnsCryptString() return stamp.dnsCryptString()
} else if stamp.proto == StampProtoTypeDoH { } else if stamp.Proto == StampProtoTypeDoH {
return stamp.dohString() return stamp.dohString()
} }
dlog.Fatal("Unsupported protocol") dlog.Fatal("Unsupported protocol")
@ -200,20 +210,20 @@ func (stamp *ServerStamp) String() string {
func (stamp *ServerStamp) dnsCryptString() string { func (stamp *ServerStamp) dnsCryptString() string {
bin := make([]uint8, 9) bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeDNSCrypt) bin[0] = uint8(StampProtoTypeDNSCrypt)
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props)) binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
serverAddrStr := stamp.serverAddrStr serverAddrStr := stamp.ServerAddrStr
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) { if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) {
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))] serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))]
} }
bin = append(bin, uint8(len(serverAddrStr))) bin = append(bin, uint8(len(serverAddrStr)))
bin = append(bin, []uint8(serverAddrStr)...) bin = append(bin, []uint8(serverAddrStr)...)
bin = append(bin, uint8(len(stamp.serverPk))) bin = append(bin, uint8(len(stamp.ServerPk)))
bin = append(bin, stamp.serverPk...) bin = append(bin, stamp.ServerPk...)
bin = append(bin, uint8(len(stamp.providerName))) bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.providerName)...) bin = append(bin, []uint8(stamp.ProviderName)...)
str := base64.RawURLEncoding.EncodeToString(bin) str := base64.RawURLEncoding.EncodeToString(bin)
@ -223,17 +233,17 @@ func (stamp *ServerStamp) dnsCryptString() string {
func (stamp *ServerStamp) dohString() string { func (stamp *ServerStamp) dohString() string {
bin := make([]uint8, 9) bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeDoH) bin[0] = uint8(StampProtoTypeDoH)
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props)) binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
serverAddrStr := stamp.serverAddrStr serverAddrStr := stamp.ServerAddrStr
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) { if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) {
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))] serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))]
} }
bin = append(bin, uint8(len(serverAddrStr))) bin = append(bin, uint8(len(serverAddrStr)))
bin = append(bin, []uint8(serverAddrStr)...) bin = append(bin, []uint8(serverAddrStr)...)
last := len(stamp.hashes) - 1 last := len(stamp.Hashes) - 1
for i, hash := range stamp.hashes { for i, hash := range stamp.Hashes {
vlen := len(hash) vlen := len(hash)
if i < last { if i < last {
vlen |= 0x80 vlen |= 0x80
@ -242,11 +252,11 @@ func (stamp *ServerStamp) dohString() string {
bin = append(bin, hash...) bin = append(bin, hash...)
} }
bin = append(bin, uint8(len(stamp.providerName))) bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.providerName)...) bin = append(bin, []uint8(stamp.ProviderName)...)
bin = append(bin, uint8(len(stamp.path))) bin = append(bin, uint8(len(stamp.Path)))
bin = append(bin, []uint8(stamp.path)...) bin = append(bin, []uint8(stamp.Path)...)
str := base64.RawURLEncoding.EncodeToString(bin) str := base64.RawURLEncoding.EncodeToString(bin)