dnscrypt-proxy/vendor/github.com/jedisct1/go-dnsstamps/dnsstamps.go

655 lines
18 KiB
Go
Raw Normal View History

2018-04-18 18:47:10 +02:00
package dnsstamps
import (
"encoding/base64"
"encoding/binary"
"encoding/hex"
2018-01-20 14:13:11 +01:00
"errors"
"fmt"
"net"
2018-02-02 15:07:12 +01:00
"strconv"
2018-01-20 14:13:11 +01:00
"strings"
)
2024-04-25 12:45:52 +02:00
const (
DefaultPort = 443
DefaultDNSPort = 53
StampScheme = "sdns://"
)
2018-04-14 15:03:21 +02:00
type ServerInformalProperties uint64
const (
2020-12-11 14:14:09 +01:00
ServerInformalPropertyDNSSEC = ServerInformalProperties(1) << 0
ServerInformalPropertyNoLog = ServerInformalProperties(1) << 1
ServerInformalPropertyNoFilter = ServerInformalProperties(1) << 2
2018-04-14 15:03:21 +02:00
)
type StampProtoType uint8
const (
2019-10-14 02:23:12 +02:00
StampProtoTypePlain = StampProtoType(0x00)
StampProtoTypeDNSCrypt = StampProtoType(0x01)
StampProtoTypeDoH = StampProtoType(0x02)
StampProtoTypeTLS = StampProtoType(0x03)
2020-12-10 22:57:31 +01:00
StampProtoTypeDoQ = StampProtoType(0x04)
2020-12-11 14:14:09 +01:00
StampProtoTypeODoHTarget = StampProtoType(0x05)
2019-10-14 02:23:12 +02:00
StampProtoTypeDNSCryptRelay = StampProtoType(0x81)
2020-12-11 14:14:09 +01:00
StampProtoTypeODoHRelay = StampProtoType(0x85)
)
func (stampProtoType *StampProtoType) String() string {
switch *stampProtoType {
case StampProtoTypePlain:
return "Plain"
case StampProtoTypeDNSCrypt:
return "DNSCrypt"
case StampProtoTypeDoH:
return "DoH"
2020-12-10 22:57:31 +01:00
case StampProtoTypeTLS:
return "TLS"
case StampProtoTypeDoQ:
return "QUIC"
2020-12-11 14:14:09 +01:00
case StampProtoTypeODoHTarget:
return "oDoH target"
2019-10-14 02:23:12 +02:00
case StampProtoTypeDNSCryptRelay:
2020-12-11 14:14:09 +01:00
return "DNSCrypt relay"
case StampProtoTypeODoHRelay:
return "oDoH relay"
default:
2020-12-11 14:14:09 +01:00
return "(unknown)"
}
}
type ServerStamp struct {
2018-04-14 15:03:21 +02:00
ServerAddrStr string
ServerPk []uint8
Hashes [][]uint8
ProviderName string
Path string
Props ServerInformalProperties
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))
2018-04-18 19:06:50 +02:00
if err != nil || len(serverPk) != 32 {
return ServerStamp{}, fmt.Errorf("Unsupported public key: [%s]", serverPkStr)
}
return ServerStamp{
2018-04-14 15:03:21 +02:00
ServerAddrStr: serverAddrStr,
ServerPk: serverPk,
ProviderName: providerName,
Props: props,
Proto: StampProtoTypeDNSCrypt,
}, nil
}
func NewServerStampFromString(stampStr string) (ServerStamp, error) {
if !strings.HasPrefix(stampStr, "sdns:") {
2020-07-07 14:12:02 +02:00
return ServerStamp{}, errors.New("Stamps are expected to start with \"sdns:\"")
2018-01-20 14:13:11 +01:00
}
stampStr = stampStr[5:]
2020-07-07 14:12:02 +02:00
stampStr = strings.TrimPrefix(stampStr, "//")
2019-09-07 11:04:40 +02:00
bin, err := base64.RawURLEncoding.Strict().DecodeString(stampStr)
2018-01-20 14:13:11 +01:00
if err != nil {
2018-01-26 20:38:31 +01:00
return ServerStamp{}, err
2018-01-20 14:13:11 +01:00
}
2018-01-26 20:38:31 +01:00
if len(bin) < 1 {
return ServerStamp{}, errors.New("Stamp is too short")
2018-01-20 14:13:11 +01:00
}
2024-04-25 12:45:52 +02:00
if bin[0] == uint8(StampProtoTypePlain) {
return newPlainDNSServerStamp(bin)
} else if bin[0] == uint8(StampProtoTypeDNSCrypt) {
return newDNSCryptServerStamp(bin)
} else if bin[0] == uint8(StampProtoTypeDoH) {
2018-01-26 22:59:16 +01:00
return newDoHServerStamp(bin)
2020-12-11 14:14:09 +01:00
} else if bin[0] == uint8(StampProtoTypeODoHTarget) {
return newODoHTargetStamp(bin)
2019-10-14 02:23:12 +02:00
} else if bin[0] == uint8(StampProtoTypeDNSCryptRelay) {
return newDNSCryptRelayStamp(bin)
2020-12-11 14:14:09 +01:00
} else if bin[0] == uint8(StampProtoTypeODoHRelay) {
return newODoHRelayStamp(bin)
2018-01-26 20:38:31 +01:00
}
return ServerStamp{}, errors.New("Unsupported stamp version or protocol")
}
2021-08-13 19:19:23 +02:00
func NewRelayAndServerStampFromString(stampStr string) (ServerStamp, ServerStamp, error) {
2024-04-25 12:45:52 +02:00
if !strings.HasPrefix(stampStr, StampScheme) {
2021-08-13 19:19:23 +02:00
return ServerStamp{}, ServerStamp{}, errors.New("Stamps are expected to start with \"sdns://\"")
}
stampStr = stampStr[7:]
parts := strings.Split(stampStr, "/")
if len(parts) != 2 {
return ServerStamp{}, ServerStamp{}, errors.New("This is not a relay+server stamp")
}
2024-04-25 12:45:52 +02:00
relayStamp, err := NewServerStampFromString(StampScheme + parts[0])
2021-08-13 19:19:23 +02:00
if err != nil {
return ServerStamp{}, ServerStamp{}, err
}
2024-04-25 12:45:52 +02:00
serverStamp, err := NewServerStampFromString(StampScheme + parts[1])
2021-08-13 19:19:23 +02:00
if err != nil {
return ServerStamp{}, ServerStamp{}, err
}
if relayStamp.Proto != StampProtoTypeDNSCryptRelay && relayStamp.Proto != StampProtoTypeODoHRelay {
return ServerStamp{}, ServerStamp{}, errors.New("First stamp is not a relay")
}
if !(serverStamp.Proto != StampProtoTypeDNSCryptRelay && serverStamp.Proto != StampProtoTypeODoHRelay) {
return ServerStamp{}, ServerStamp{}, errors.New("Second stamp is a relay")
}
return relayStamp, serverStamp, nil
}
2024-04-25 12:45:52 +02:00
// id(u8)=0x00 props 0x00 addrLen(1) serverAddr
func newPlainDNSServerStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{Proto: StampProtoTypePlain}
if len(bin) < 1+8+1+1 {
return stamp, errors.New("Stamp is too short")
}
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin)
pos := 9
length := int(bin[pos])
if 1+length > binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.ServerAddrStr = string(bin[pos : pos+length])
pos += length
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
if colIndex < bracketIndex {
colIndex = -1
}
if colIndex < 0 {
colIndex = len(stamp.ServerAddrStr) // DefaultDNSPort
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultDNSPort)
}
if colIndex >= len(stamp.ServerAddrStr)-1 {
return stamp, errors.New("Invalid stamp (empty port)")
}
ipOnly := stamp.ServerAddrStr[:colIndex]
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
return stamp, errors.New("Invalid stamp (port range)")
}
if net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
return stamp, errors.New("Invalid stamp (IP address)")
}
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
return stamp, nil
}
// id(u8)=0x01 props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName
func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) {
2018-04-14 15:03:21 +02:00
stamp := ServerStamp{Proto: StampProtoTypeDNSCrypt}
if len(bin) < 66 {
return stamp, errors.New("Stamp is too short")
}
2018-04-14 15:03:21 +02:00
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin)
pos := 9
2019-07-06 18:03:41 +02:00
length := int(bin[pos])
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.ServerAddrStr = string(bin[pos : pos+length])
pos += length
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
if colIndex < bracketIndex {
colIndex = -1
}
if colIndex < 0 {
colIndex = len(stamp.ServerAddrStr)
2018-04-14 15:03:21 +02:00
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
}
2019-07-06 18:03:41 +02:00
if colIndex >= len(stamp.ServerAddrStr)-1 {
return stamp, errors.New("Invalid stamp (empty port)")
}
ipOnly := stamp.ServerAddrStr[:colIndex]
2024-04-25 12:45:52 +02:00
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
2019-07-06 18:03:41 +02:00
return stamp, errors.New("Invalid stamp (port range)")
}
if net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
return stamp, errors.New("Invalid stamp (IP address)")
}
2019-07-06 18:03:41 +02:00
length = int(bin[pos])
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.ServerPk = bin[pos : pos+length]
pos += length
2019-07-06 18:03:41 +02:00
length = int(bin[pos])
if length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.ProviderName = string(bin[pos : pos+length])
pos += length
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
return stamp, nil
}
2020-12-10 22:57:31 +01:00
// id(u8)=0x02 props addrLen(1) serverAddr hashLen(1) hash hostNameLen(1) hostName pathLen(1) path
2018-01-26 20:38:31 +01:00
func newDoHServerStamp(bin []byte) (ServerStamp, error) {
2018-04-14 15:03:21 +02:00
stamp := ServerStamp{Proto: StampProtoTypeDoH}
2022-03-28 12:35:01 +02:00
if len(bin) < 15 {
2018-03-02 02:17:07 +01:00
return stamp, errors.New("Stamp is too short")
2018-02-04 11:04:29 +01:00
}
2018-04-14 15:03:21 +02:00
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
2018-01-26 20:38:31 +01:00
binLen := len(bin)
pos := 9
2019-07-06 18:03:41 +02:00
length := int(bin[pos])
if 1+length >= binLen-pos {
2018-01-26 20:38:31 +01:00
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.ServerAddrStr = string(bin[pos : pos+length])
pos += length
2018-01-26 20:38:31 +01:00
for {
vlen := int(bin[pos])
2019-07-06 18:03:41 +02:00
length = vlen & ^0x80
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
if length > 0 {
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
}
2019-07-06 18:03:41 +02:00
pos += length
if vlen&0x80 != 0x80 {
break
}
2018-01-26 20:38:31 +01:00
}
2019-07-06 18:03:41 +02:00
length = int(bin[pos])
if 1+length >= binLen-pos {
2018-01-26 20:38:31 +01:00
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.ProviderName = string(bin[pos : pos+length])
pos += length
2018-01-26 20:38:31 +01:00
2019-07-06 18:03:41 +02:00
length = int(bin[pos])
if length >= binLen-pos {
2018-01-26 20:38:31 +01:00
return stamp, errors.New("Invalid stamp")
}
pos++
2019-07-06 18:03:41 +02:00
stamp.Path = string(bin[pos : pos+length])
pos += length
2018-01-26 20:38:31 +01:00
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
2019-07-06 18:03:41 +02:00
if len(stamp.ServerAddrStr) > 0 {
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
if colIndex < bracketIndex {
colIndex = -1
}
if colIndex < 0 {
colIndex = len(stamp.ServerAddrStr)
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
}
if colIndex >= len(stamp.ServerAddrStr)-1 {
return stamp, errors.New("Invalid stamp (empty port)")
}
ipOnly := stamp.ServerAddrStr[:colIndex]
2024-04-25 12:45:52 +02:00
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
2019-07-06 18:03:41 +02:00
return stamp, errors.New("Invalid stamp (port range)")
}
if net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
return stamp, errors.New("Invalid stamp (IP address)")
}
}
2018-01-26 20:38:31 +01:00
return stamp, nil
}
2020-12-11 14:14:09 +01:00
// id(u8)=0x05 props hostNameLen(1) hostName pathLen(1) path
2020-12-10 22:57:31 +01:00
2020-12-11 14:14:09 +01:00
func newODoHTargetStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{Proto: StampProtoTypeODoHTarget}
if len(bin) < 12 {
2020-12-10 22:57:31 +01:00
return stamp, errors.New("Stamp is too short")
}
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin)
pos := 9
length := int(bin[pos])
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.ProviderName = string(bin[pos : pos+length])
pos += length
length = int(bin[pos])
if length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.Path = string(bin[pos : pos+length])
pos += length
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
return stamp, nil
}
2019-10-14 02:23:12 +02:00
// id(u8)=0x81 addrLen(1) serverAddr
func newDNSCryptRelayStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{Proto: StampProtoTypeDNSCryptRelay}
2022-03-28 12:35:01 +02:00
if len(bin) < 9 {
2019-10-14 02:23:12 +02:00
return stamp, errors.New("Stamp is too short")
}
binLen := len(bin)
2019-10-14 10:50:09 +02:00
pos := 1
2019-10-14 02:23:12 +02:00
length := int(bin[pos])
2019-10-14 10:50:09 +02:00
if 1+length > binLen-pos {
2019-10-14 02:23:12 +02:00
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.ServerAddrStr = string(bin[pos : pos+length])
pos += length
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
if colIndex < bracketIndex {
colIndex = -1
}
if colIndex < 0 {
colIndex = len(stamp.ServerAddrStr)
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
}
if colIndex >= len(stamp.ServerAddrStr)-1 {
return stamp, errors.New("Invalid stamp (empty port)")
}
ipOnly := stamp.ServerAddrStr[:colIndex]
2024-04-25 12:45:52 +02:00
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
2019-10-14 02:23:12 +02:00
return stamp, errors.New("Invalid stamp (port range)")
}
if net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
return stamp, errors.New("Invalid stamp (IP address)")
}
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
return stamp, nil
}
2020-12-11 14:14:09 +01:00
// id(u8)=0x85 props addrLen(1) serverAddr hashLen(1) hash hostNameLen(1) hostName pathLen(1) path
func newODoHRelayStamp(bin []byte) (ServerStamp, error) {
stamp := ServerStamp{Proto: StampProtoTypeODoHRelay}
if len(bin) < 13 {
return stamp, errors.New("Stamp is too short")
}
stamp.Props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin)
pos := 9
length := int(bin[pos])
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.ServerAddrStr = string(bin[pos : pos+length])
pos += length
for {
vlen := int(bin[pos])
length = vlen & ^0x80
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
if length > 0 {
stamp.Hashes = append(stamp.Hashes, bin[pos:pos+length])
}
pos += length
if vlen&0x80 != 0x80 {
break
}
}
length = int(bin[pos])
if 1+length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.ProviderName = string(bin[pos : pos+length])
pos += length
length = int(bin[pos])
if length >= binLen-pos {
return stamp, errors.New("Invalid stamp")
}
pos++
stamp.Path = string(bin[pos : pos+length])
pos += length
if pos != binLen {
return stamp, errors.New("Invalid stamp (garbage after end)")
}
if len(stamp.ServerAddrStr) > 0 {
colIndex := strings.LastIndex(stamp.ServerAddrStr, ":")
bracketIndex := strings.LastIndex(stamp.ServerAddrStr, "]")
if colIndex < bracketIndex {
colIndex = -1
}
if colIndex < 0 {
colIndex = len(stamp.ServerAddrStr)
stamp.ServerAddrStr = fmt.Sprintf("%s:%d", stamp.ServerAddrStr, DefaultPort)
}
if colIndex >= len(stamp.ServerAddrStr)-1 {
return stamp, errors.New("Invalid stamp (empty port)")
}
ipOnly := stamp.ServerAddrStr[:colIndex]
2024-04-25 12:45:52 +02:00
if err := validatePort(stamp.ServerAddrStr[colIndex+1:]); err != nil {
2020-12-11 14:14:09 +01:00
return stamp, errors.New("Invalid stamp (port range)")
}
if net.ParseIP(strings.TrimRight(strings.TrimLeft(ipOnly, "["), "]")) == nil {
return stamp, errors.New("Invalid stamp (IP address)")
}
}
return stamp, nil
}
2024-04-25 12:45:52 +02:00
func validatePort(port string) error {
if _, err := strconv.ParseUint(port, 10, 16); err != nil {
return errors.New("Invalid port")
}
return nil
}
func (stamp *ServerStamp) String() string {
2024-04-25 12:45:52 +02:00
if stamp.Proto == StampProtoTypePlain {
return stamp.plainStrng()
} else if stamp.Proto == StampProtoTypeDNSCrypt {
return stamp.dnsCryptString()
2018-04-14 15:03:21 +02:00
} else if stamp.Proto == StampProtoTypeDoH {
2018-01-26 20:38:31 +01:00
return stamp.dohString()
2020-12-11 14:14:09 +01:00
} else if stamp.Proto == StampProtoTypeODoHTarget {
return stamp.oDohTargetString()
2019-10-14 02:23:12 +02:00
} else if stamp.Proto == StampProtoTypeDNSCryptRelay {
return stamp.dnsCryptRelayString()
2020-12-11 14:14:09 +01:00
} else if stamp.Proto == StampProtoTypeODoHRelay {
return stamp.oDohRelayString()
2018-01-26 20:38:31 +01:00
}
2018-04-14 16:30:22 +02:00
panic("Unsupported protocol")
2018-01-26 20:38:31 +01:00
}
2024-04-25 12:45:52 +02:00
func (stamp *ServerStamp) plainStrng() string {
bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypePlain)
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
serverAddrStr := stamp.ServerAddrStr
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultDNSPort)) {
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultDNSPort))]
}
bin = append(bin, uint8(len(serverAddrStr)))
bin = append(bin, []uint8(serverAddrStr)...)
str := base64.RawURLEncoding.EncodeToString(bin)
return StampScheme + str
}
func (stamp *ServerStamp) dnsCryptString() string {
bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeDNSCrypt)
2018-04-14 15:03:21 +02:00
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
2018-04-14 15:03:21 +02:00
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)...)
2018-04-14 15:03:21 +02:00
bin = append(bin, uint8(len(stamp.ServerPk)))
bin = append(bin, stamp.ServerPk...)
2018-04-14 15:03:21 +02:00
bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.ProviderName)...)
str := base64.RawURLEncoding.EncodeToString(bin)
2024-04-25 12:45:52 +02:00
return StampScheme + str
}
2018-01-26 20:38:31 +01:00
func (stamp *ServerStamp) dohString() string {
bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeDoH)
2018-04-14 15:03:21 +02:00
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
2018-01-26 20:38:31 +01:00
2018-04-14 15:03:21 +02:00
serverAddrStr := stamp.ServerAddrStr
2018-02-02 15:07:12 +01:00
if strings.HasSuffix(serverAddrStr, ":"+strconv.Itoa(DefaultPort)) {
serverAddrStr = serverAddrStr[:len(serverAddrStr)-1-len(strconv.Itoa(DefaultPort))]
2018-01-30 16:10:46 +01:00
}
bin = append(bin, uint8(len(serverAddrStr)))
bin = append(bin, []uint8(serverAddrStr)...)
2018-01-26 20:38:31 +01:00
2020-12-01 14:46:14 +01:00
if len(stamp.Hashes) == 0 {
bin = append(bin, uint8(0))
} else {
last := len(stamp.Hashes) - 1
for i, hash := range stamp.Hashes {
vlen := len(hash)
if i < last {
vlen |= 0x80
}
bin = append(bin, uint8(vlen))
bin = append(bin, hash...)
}
}
2018-01-26 20:38:31 +01:00
2018-04-14 15:03:21 +02:00
bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.ProviderName)...)
2018-01-26 20:38:31 +01:00
2018-04-14 15:03:21 +02:00
bin = append(bin, uint8(len(stamp.Path)))
bin = append(bin, []uint8(stamp.Path)...)
2018-01-26 20:38:31 +01:00
str := base64.RawURLEncoding.EncodeToString(bin)
2024-04-25 12:45:52 +02:00
return StampScheme + str
2018-01-26 20:38:31 +01:00
}
2019-10-14 02:23:12 +02:00
2020-12-11 14:14:09 +01:00
func (stamp *ServerStamp) oDohTargetString() string {
2020-12-10 22:57:31 +01:00
bin := make([]uint8, 9)
2020-12-11 14:14:09 +01:00
bin[0] = uint8(StampProtoTypeODoHTarget)
2020-12-10 22:57:31 +01:00
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.Props))
bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.ProviderName)...)
bin = append(bin, uint8(len(stamp.Path)))
bin = append(bin, []uint8(stamp.Path)...)
str := base64.RawURLEncoding.EncodeToString(bin)
2024-04-25 12:45:52 +02:00
return StampScheme + str
2020-12-10 22:57:31 +01:00
}
2019-10-14 02:23:12 +02:00
func (stamp *ServerStamp) dnsCryptRelayString() string {
bin := make([]uint8, 1)
bin[0] = uint8(StampProtoTypeDNSCryptRelay)
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)...)
str := base64.RawURLEncoding.EncodeToString(bin)
2024-04-25 12:45:52 +02:00
return StampScheme + str
2019-10-14 02:23:12 +02:00
}
2020-12-11 14:14:09 +01:00
func (stamp *ServerStamp) oDohRelayString() string {
bin := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeODoHRelay)
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)...)
if len(stamp.Hashes) == 0 {
bin = append(bin, uint8(0))
} else {
last := len(stamp.Hashes) - 1
for i, hash := range stamp.Hashes {
vlen := len(hash)
if i < last {
vlen |= 0x80
}
bin = append(bin, uint8(vlen))
bin = append(bin, hash...)
}
}
bin = append(bin, uint8(len(stamp.ProviderName)))
bin = append(bin, []uint8(stamp.ProviderName)...)
bin = append(bin, uint8(len(stamp.Path)))
bin = append(bin, []uint8(stamp.Path)...)
str := base64.RawURLEncoding.EncodeToString(bin)
2024-04-25 12:45:52 +02:00
return StampScheme + str
2020-12-11 14:14:09 +01:00
}