Compare commits

..

8 Commits

Author SHA1 Message Date
James Swineson
9985c4b279 fix relative path 2019-03-26 15:57:01 +08:00
James Swineson
97a27e60e1 update comments 2019-03-26 15:46:57 +08:00
James Swineson
ca14db8929 move package.sh to contrib 2019-03-26 12:30:57 +08:00
James Swineson
a95e3e5f39 add networkmanager dispatcher script 2019-03-26 12:28:14 +08:00
James Swineson
5010a16458 initial dirty auto packaging 2019-03-26 12:16:07 +08:00
Ming Aldrich-Gan
2332d9b7c1 Add local_addr configuration for doh-server (#39)
* Add local_addr configuration for doh-server

This commit adds a `local_addr` string value to `doh-server.conf`, specifying the IP address and port from which outgoing calls to upstream DNS resolvers should originate. This value is set as the `udpClient`'s and `tcpClient`'s `Dialer.LocalAddr` when initializing a `NewServer`. If the value is left empty in `doh-server.conf`, it defaults to the first `listen` address (which in turn defaults to `"127.0.0.1:8053"`).

One use case for this would be if `doh-server` is proxying requests to a local DNS resolver (e.g. `unbound` or Pi-hole). Up to version 2.0.0, all DNS queries from `doh-server` are sent from `127.0.0.1` (even if the `listen` address is set to a different loopback IP address), making it hard to distinguish them from all other local DNS queries from the same machine in the query logs.

* Revert defaulting of local_addr to listen address

This commit reverts to the existing behavior when `conf.LocalAddr == ""`, i.e. letting `dns.Client` instantiate its own `Dialer` with the default local address.

* Fixup comment in configuration file

* Log errors from Dialer instantiation (e.g. if LocalAddr port is missing)

* Fixup other comment in configuration file

* Return error and log fatal
2019-03-25 04:01:32 +08:00
Star Brilliant
7f5a23584f Release 2.0.1 2019-03-24 19:11:12 +08:00
Sherlock Holo
17e5848178 Fix random selector (#41)
* Fix a bug: when only have one upstream, random selector will panic

Signed-off-by: Sherlock Holo <sherlockya@gmail.com>
2019-03-24 09:13:14 +08:00
11 changed files with 217 additions and 12 deletions

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@
*.dll *.dll
*.so *.so
*.dylib *.dylib
build/
# Test binary, build with `go test -c` # Test binary, build with `go test -c`
*.test *.test

View File

@@ -4,6 +4,10 @@ This Changelog records major changes between versions.
Not all changes are recorded. Please check git log for details. Not all changes are recorded. Please check git log for details.
## Version 2.0.1
- Fix a crash with the random load balancing algorithm.
## Version 2.0.0 ## Version 2.0.0
**This is a breaking change!** Please update the configuration file after upgrading. **This is a breaking change!** Please update the configuration file after upgrading.

173
contrib/package.sh Executable file
View File

@@ -0,0 +1,173 @@
#!/bin/bash
set -euo pipefail
# This is a script used for automated packaging.
# Debian maintainers please don't use this.
#
# Environment assumption:
# * Ubuntu 16.04
# * run with normal user
# * sudo with no password
# * go and fpm is pre-installed
# * rpmbuild is required if you need rpm packages
#
# Compatible with Azure DevOps hosted Ubuntu 16.04 agent
export DEBIAN_FRONTEND="noninteractive"
export DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/..
export BUILD_BINARIESDIRECTORY="${BUILD_BINARIESDIRECTORY:-${DIR}/build/bin}"
export BUILD_ARTIFACTSTAGINGDIRECTORY="${BUILD_ARTIFACTSTAGINGDIRECTORY:-${DIR}/build/packages}"
export TMP_DIRECTORY="/tmp/dohbuild"
export GOPATH="${GOPATH:-/tmp/go}"
export GOBIN="${GOBIN:-/tmp/go/bin}"
function prepare_env() {
echo "Checking dependencies"
if ! [ -x "$(command -v go)" ]; then
echo "Please install golang"
exit 1
fi
if [ -x "$(command -v apt-get)" ]; then
sudo apt-get -y update
fi
if ! [ -x "$(command -v rpmbuild)" ]; then
# TODO: correctly install rpmbuild
! sudo apt-get -y install rpmbuild
fi
# if ! [ -x "$(command -v upx)" ]; then
# sudo apt-get -y install upx
# fi
echo "Creating directories"
mkdir -p "${BUILD_BINARIESDIRECTORY}/nm-dispatcher"
mkdir -p "${BUILD_BINARIESDIRECTORY}/launchd"
mkdir -p "${BUILD_BINARIESDIRECTORY}/systemd"
mkdir -p "${BUILD_BINARIESDIRECTORY}/config"
mkdir -p "${BUILD_ARTIFACTSTAGINGDIRECTORY}"
mkdir -p "${TMP_DIRECTORY}"
}
function build_common() {
cp NetworkManager/dispatcher.d/* "${BUILD_BINARIESDIRECTORY}"/nm-dispatcher
cp launchd/*.plist "${BUILD_BINARIESDIRECTORY}"/launchd
cp systemd/*.service "${BUILD_BINARIESDIRECTORY}"/systemd
cp doh-server/doh-server.conf "${BUILD_BINARIESDIRECTORY}"/config
cp doh-client/doh-client.conf "${BUILD_BINARIESDIRECTORY}"/config
}
# used to get version
function build_native() {
echo "Building a native binary..."
go build -ldflags="-s -w" -o ${BUILD_BINARIESDIRECTORY}/"${EXE}"-native
}
function build() {
echo "Building ${EXE} for OS=$1 ARCH=$2"
env GOOS="$1" GOARCH="$2" go build -ldflags="-s -w" -o ${BUILD_BINARIESDIRECTORY}/"${EXE}"-"$3"
# echo "Compressing executable"
# ! upx --ultra-brute ${BUILD_BINARIESDIRECTORY}/${EXE}-"$3" || true
}
function package() {
VERSION=$("${BUILD_BINARIESDIRECTORY}/${EXE}-native" --version | head -n 1 | cut -d" " -f2)
REVISION=$(git log --pretty=format:'%h' -n 1)
echo "Packaging ${EXE} ${VERSION} for OS=$1 ARCH=$2 TYPE=$3 DST=$4"
! rm -rf "${TMP_DIRECTORY}"/*
mkdir -p "${TMP_DIRECTORY}"/usr/bin
cp "${BUILD_BINARIESDIRECTORY}"/"${EXE}"-"$3" "${TMP_DIRECTORY}"/usr/bin/"${EXE}"
mkdir -p "${TMP_DIRECTORY}"/usr/lib/systemd/system
cp "${BUILD_BINARIESDIRECTORY}"/systemd/"${EXE}".service "${TMP_DIRECTORY}"/usr/lib/systemd/system
mkdir -p "${TMP_DIRECTORY}"/etc/dns-over-https
cp "${BUILD_BINARIESDIRECTORY}"/config/"${EXE}".conf "${TMP_DIRECTORY}"/etc/dns-over-https
mkdir -p "${TMP_DIRECTORY}"/etc/NetworkManager/dispatcher.d
cp "${BUILD_BINARIESDIRECTORY}"/nm-dispatcher/"${EXE}" "${TMP_DIRECTORY}"/etc/NetworkManager/dispatcher.d
# call fpm
fpm --input-type dir \
--output-type $4 \
--chdir "${TMP_DIRECTORY}" \
--package "${BUILD_ARTIFACTSTAGINGDIRECTORY}" \
--name "${EXE}" \
--description "${DESCR}" \
--version "${VERSION}" \
--iteration "${REVISION}" \
--url "https://github.com/m13253/dns-over-https" \
--vendor "Star Brilliant <coder@poorlab.com>" \
--license "MIT License" \
--category "net" \
--maintainer "James Swineson <autopkg@public.swineson.me>" \
--architecture "$2" \
--force \
.
}
cd "${DIR}"/..
prepare_env
make deps
build_common
pushd doh-server
export EXE="doh-server"
export DESCR="DNS-over-HTTPS Server"
build_native
build linux amd64 linux-amd64
package linux amd64 linux-amd64 deb
! package linux amd64 linux-amd64 rpm
package linux amd64 linux-amd64 pacman
build linux arm linux-armhf
package linux arm linux-armhf deb
! package linux arm linux-armhf rpm
package linux arm linux-armhf pacman
build linux arm64 linux-arm64
package linux arm64 linux-arm64 deb
! package linux arm64 linux-arm64 rpm
package linux arm64 linux-arm64 pacman
# build darwin amd64 darwin-amd64
# build windows 386 windows-x86.exe
# build windows amd64 windows-amd64.exe
popd
pushd doh-client
export EXE="doh-client"
export DESCR="DNS-over-HTTPS Client"
build_native
build linux amd64 linux-amd64
package linux amd64 linux-amd64 deb
! package linux amd64 linux-amd64 rpm
package linux amd64 linux-amd64 pacman
build linux arm linux-armhf
package linux arm linux-armhf deb
! package linux arm linux-armhf rpm
package linux arm linux-armhf pacman
build linux arm64 linux-arm64
package linux arm64 linux-arm64 deb
! package linux arm64 linux-arm64 rpm
package linux arm64 linux-arm64 pacman
# build darwin amd64 darwin-amd64
# build windows 386 windows-x86.exe
# build windows amd64 windows-amd64.exe
popd

View File

@@ -155,7 +155,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
switch c.conf.Upstream.UpstreamSelector { switch c.conf.Upstream.UpstreamSelector {
case config.NginxWRR: case config.NginxWRR:
if c.conf.Other.Verbose { if c.conf.Other.Verbose {
log.Println(config.NginxWRR, " mode start") log.Println(config.NginxWRR, "mode start")
} }
s := selector.NewNginxWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second) s := selector.NewNginxWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second)
@@ -175,7 +175,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
case config.LVSWRR: case config.LVSWRR:
if c.conf.Other.Verbose { if c.conf.Other.Verbose {
log.Println(config.LVSWRR, " mode start") log.Println(config.LVSWRR, "mode start")
} }
s := selector.NewLVSWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second) s := selector.NewLVSWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second)
@@ -195,7 +195,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
default: default:
if c.conf.Other.Verbose { if c.conf.Other.Verbose {
log.Println(config.Random, " mode start") log.Println(config.Random, "mode start")
} }
// if selector is invalid or random, use random selector, or should we stop program and let user knows he is wrong? // if selector is invalid or random, use random selector, or should we stop program and let user knows he is wrong?

View File

@@ -42,7 +42,7 @@ func (rs *RandomSelector) Add(url string, upstreamType UpstreamType) (err error)
} }
func (rs *RandomSelector) Get() *Upstream { func (rs *RandomSelector) Get() *Upstream {
return rs.upstreams[rand.Intn(len(rs.upstreams)-1)] return rs.upstreams[rand.Intn(len(rs.upstreams))]
} }
func (rs *RandomSelector) StartEvaluate() {} func (rs *RandomSelector) StartEvaluate() {}

View File

@@ -24,6 +24,6 @@
package main package main
const ( const (
VERSION = "2.0.0" VERSION = "2.0.1"
USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)" USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)"
) )

View File

@@ -31,6 +31,7 @@ import (
type config struct { type config struct {
Listen []string `toml:"listen"` Listen []string `toml:"listen"`
LocalAddr string `toml:"local_addr"`
Cert string `toml:"cert"` Cert string `toml:"cert"`
Key string `toml:"key"` Key string `toml:"key"`
Path string `toml:"path"` Path string `toml:"path"`

View File

@@ -4,6 +4,10 @@ listen = [
"[::1]:8053", "[::1]:8053",
] ]
# Local address and port for upstream DNS
# If left empty, a local address is automatically chosen.
local_addr = ""
# TLS certification file # TLS certification file
# If left empty, plain-text HTTP will be used. # If left empty, plain-text HTTP will be used.
# You are recommended to leave empty and to use a server load balancer (e.g. # You are recommended to leave empty and to use a server load balancer (e.g.

View File

@@ -110,6 +110,9 @@ func main() {
conf.Verbose = true conf.Verbose = true
} }
server := NewServer(conf) server, err := NewServer(conf)
if err != nil {
log.Fatalln(err)
}
_ = server.Start() _ = server.Start()
} }

View File

@@ -56,22 +56,41 @@ type DNSRequest struct {
errtext string errtext string
} }
func NewServer(conf *config) (s *Server) { func NewServer(conf *config) (*Server, error) {
s = &Server{ timeout := time.Duration(conf.Timeout) * time.Second
s := &Server{
conf: conf, conf: conf,
udpClient: &dns.Client{ udpClient: &dns.Client{
Net: "udp", Net: "udp",
UDPSize: dns.DefaultMsgSize, UDPSize: dns.DefaultMsgSize,
Timeout: time.Duration(conf.Timeout) * time.Second, Timeout: timeout,
}, },
tcpClient: &dns.Client{ tcpClient: &dns.Client{
Net: "tcp", Net: "tcp",
Timeout: time.Duration(conf.Timeout) * time.Second, Timeout: timeout,
}, },
servemux: http.NewServeMux(), servemux: http.NewServeMux(),
} }
if conf.LocalAddr != "" {
udpLocalAddr, err := net.ResolveUDPAddr("udp", conf.LocalAddr)
if err != nil {
return nil, err
}
tcpLocalAddr, err := net.ResolveTCPAddr("tcp", conf.LocalAddr)
if err != nil {
return nil, err
}
s.udpClient.Dialer = &net.Dialer{
Timeout: timeout,
LocalAddr: udpLocalAddr,
}
s.tcpClient.Dialer = &net.Dialer{
Timeout: timeout,
LocalAddr: tcpLocalAddr,
}
}
s.servemux.HandleFunc(conf.Path, s.handlerFunc) s.servemux.HandleFunc(conf.Path, s.handlerFunc)
return return s, nil
} }
func (s *Server) Start() error { func (s *Server) Start() error {

View File

@@ -24,6 +24,6 @@
package main package main
const ( const (
VERSION = "2.0.0" VERSION = "2.0.1"
USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)" USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)"
) )