mirror of
https://github.com/m13253/dns-over-https.git
synced 2026-04-01 13:55:39 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51b065eed7 | ||
|
|
a58607dc3d | ||
|
|
cf94354b08 | ||
|
|
f2e3a642e3 | ||
|
|
88b3c95710 | ||
|
|
93b70f3941 | ||
|
|
76c40fb4dc | ||
|
|
174a465ac8 |
@@ -4,6 +4,15 @@ 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 1.3.6
|
||||||
|
|
||||||
|
- We have a logger for macOS platform now, so logs can be sent to Console.app
|
||||||
|
- Add an option to disable IPv6, this option is available to client only
|
||||||
|
|
||||||
|
## Version 1.3.5
|
||||||
|
|
||||||
|
- Limit the frequency of creating HTTP client on bad network condition
|
||||||
|
|
||||||
## Version 1.3.4
|
## Version 1.3.4
|
||||||
|
|
||||||
- doh-client now silently fails in case of network error to prevent caching of SERVFAIL
|
- doh-client now silently fails in case of network error to prevent caching of SERVFAIL
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -11,9 +11,15 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
all: doh-client/doh-client doh-server/doh-server
|
all: doh-client/doh-client doh-server/doh-server
|
||||||
|
if [ "`uname`" = "Darwin" ]; then \
|
||||||
|
$(MAKE) -C darwin-wrapper; \
|
||||||
|
fi
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f doh-client/doh-client doh-server/doh-server
|
rm -f doh-client/doh-client doh-server/doh-server
|
||||||
|
if [ "`uname`" = "Darwin" ]; then \
|
||||||
|
$(MAKE) -C darwin-wrapper clean; \
|
||||||
|
fi
|
||||||
|
|
||||||
install:
|
install:
|
||||||
[ -e doh-client/doh-client ] || $(MAKE) doh-client/doh-client
|
[ -e doh-client/doh-client ] || $(MAKE) doh-client/doh-client
|
||||||
@@ -28,6 +34,7 @@ install:
|
|||||||
$(MAKE) -C systemd install "DESTDIR=$(DESTDIR)"; \
|
$(MAKE) -C systemd install "DESTDIR=$(DESTDIR)"; \
|
||||||
$(MAKE) -C NetworkManager install "DESTDIR=$(DESTDIR)"; \
|
$(MAKE) -C NetworkManager install "DESTDIR=$(DESTDIR)"; \
|
||||||
elif [ "`uname`" = "Darwin" ]; then \
|
elif [ "`uname`" = "Darwin" ]; then \
|
||||||
|
$(MAKE) -C darwin-wrapper install "DESTDIR=$(DESTDIR)" "PREFIX=$(PREFIX)"; \
|
||||||
$(MAKE) -C launchd install "DESTDIR=$(DESTDIR)"; \
|
$(MAKE) -C launchd install "DESTDIR=$(DESTDIR)"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
19
darwin-wrapper/Makefile
Normal file
19
darwin-wrapper/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.PHONY: all clean install uninstall
|
||||||
|
|
||||||
|
SWIFTC = swiftc
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
|
all: doh-logger
|
||||||
|
|
||||||
|
doh-logger: doh-logger.swift
|
||||||
|
$(SWIFTC) -o $@ -O $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f doh-logger
|
||||||
|
|
||||||
|
install: doh-logger
|
||||||
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
|
install -m0755 doh-logger $(DESTDIR)$(PREFIX)/bin
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/bin/doh-logger
|
||||||
94
darwin-wrapper/doh-logger.swift
Normal file
94
darwin-wrapper/doh-logger.swift
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/swift
|
||||||
|
|
||||||
|
/*
|
||||||
|
DNS-over-HTTPS
|
||||||
|
Copyright (C) 2017-2018 Star Brilliant <m13253@hotmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import os.log
|
||||||
|
|
||||||
|
if CommandLine.arguments.count < 3 {
|
||||||
|
let programName = CommandLine.arguments[0]
|
||||||
|
print("Usage: \(programName) LOG_NAME PROGRAM [ARGUMENTS]\n")
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
let logSubsystem = CommandLine.arguments[1]
|
||||||
|
let logger = OSLog(subsystem: logSubsystem, category: "default")
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
var buffer = Data()
|
||||||
|
NotificationCenter.default.addObserver(forName: FileHandle.readCompletionNotification, object: pipe.fileHandleForReading, queue: nil) { notification in
|
||||||
|
let data = notification.userInfo?["NSFileHandleNotificationDataItem"] as? Data ?? Data()
|
||||||
|
buffer.append(data)
|
||||||
|
var lastIndex = 0
|
||||||
|
for (i, byte) in buffer.enumerated() {
|
||||||
|
if byte == 0x0a {
|
||||||
|
let line = String(data: buffer.subdata(in: lastIndex..<i), encoding: .utf8) ?? ""
|
||||||
|
print(line)
|
||||||
|
os_log("%{public}@", log: logger, line)
|
||||||
|
lastIndex = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer = buffer.subdata(in: lastIndex..<buffer.count)
|
||||||
|
if data.count == 0 && buffer.count != 0 {
|
||||||
|
let line = String(data: buffer, encoding: .utf8) ?? ""
|
||||||
|
print(line, terminator: "")
|
||||||
|
os_log("%{public}@", log: logger, line)
|
||||||
|
}
|
||||||
|
pipe.fileHandleForReading.readInBackgroundAndNotify()
|
||||||
|
}
|
||||||
|
pipe.fileHandleForReading.readInBackgroundAndNotify()
|
||||||
|
|
||||||
|
let process = Process()
|
||||||
|
process.arguments = Array(CommandLine.arguments[3...])
|
||||||
|
process.executableURL = URL(fileURLWithPath: CommandLine.arguments[2])
|
||||||
|
process.standardError = pipe.fileHandleForWriting
|
||||||
|
process.standardInput = FileHandle.standardInput
|
||||||
|
process.standardOutput = pipe.fileHandleForWriting
|
||||||
|
NotificationCenter.default.addObserver(forName: Process.didTerminateNotification, object: process, queue: nil) { notification in
|
||||||
|
if buffer.count != 0 {
|
||||||
|
let line = String(data: buffer, encoding: .utf8) ?? ""
|
||||||
|
print(line, terminator: "")
|
||||||
|
os_log("%{public}@", log: logger, line)
|
||||||
|
}
|
||||||
|
exit(process.terminationStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
let SIGINTSource = DispatchSource.makeSignalSource(signal: SIGINT)
|
||||||
|
let SIGTERMSource = DispatchSource.makeSignalSource(signal: SIGTERM)
|
||||||
|
SIGINTSource.setEventHandler(handler: process.interrupt)
|
||||||
|
SIGTERMSource.setEventHandler(handler: process.terminate)
|
||||||
|
signal(SIGINT, SIG_IGN)
|
||||||
|
signal(SIGTERM, SIG_IGN)
|
||||||
|
SIGINTSource.resume()
|
||||||
|
SIGTERMSource.resume()
|
||||||
|
|
||||||
|
do {
|
||||||
|
try process.run()
|
||||||
|
} catch {
|
||||||
|
let errorMessage = error.localizedDescription
|
||||||
|
print(errorMessage)
|
||||||
|
os_log("%{public}@", log: logger, type: .fault, errorMessage)
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
RunLoop.current.run()
|
||||||
@@ -40,15 +40,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
conf *config
|
conf *config
|
||||||
bootstrap []string
|
bootstrap []string
|
||||||
udpServers []*dns.Server
|
udpServers []*dns.Server
|
||||||
tcpServers []*dns.Server
|
tcpServers []*dns.Server
|
||||||
bootstrapResolver *net.Resolver
|
bootstrapResolver *net.Resolver
|
||||||
cookieJar *cookiejar.Jar
|
cookieJar *cookiejar.Jar
|
||||||
httpClientMux *sync.RWMutex
|
httpClientMux *sync.RWMutex
|
||||||
httpTransport *http.Transport
|
httpTransport *http.Transport
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
httpClientLastCreate time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSRequest struct {
|
type DNSRequest struct {
|
||||||
@@ -124,16 +125,20 @@ func NewClient(conf *config) (c *Client, err error) {
|
|||||||
func (c *Client) newHTTPClient() error {
|
func (c *Client) newHTTPClient() error {
|
||||||
c.httpClientMux.Lock()
|
c.httpClientMux.Lock()
|
||||||
defer c.httpClientMux.Unlock()
|
defer c.httpClientMux.Unlock()
|
||||||
|
if !c.httpClientLastCreate.IsZero() && time.Now().Sub(c.httpClientLastCreate) < time.Duration(c.conf.Timeout)*time.Second {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if c.httpTransport != nil {
|
if c.httpTransport != nil {
|
||||||
c.httpTransport.CloseIdleConnections()
|
c.httpTransport.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
Timeout: time.Duration(c.conf.Timeout) * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
DualStack: true,
|
||||||
|
Resolver: c.bootstrapResolver,
|
||||||
|
}
|
||||||
c.httpTransport = &http.Transport{
|
c.httpTransport = &http.Transport{
|
||||||
DialContext: (&net.Dialer{
|
DialContext: dialer.DialContext,
|
||||||
Timeout: time.Duration(c.conf.Timeout) * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
Resolver: c.bootstrapResolver,
|
|
||||||
}).DialContext,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
@@ -142,6 +147,14 @@ func (c *Client) newHTTPClient() error {
|
|||||||
ResponseHeaderTimeout: time.Duration(c.conf.Timeout) * time.Second,
|
ResponseHeaderTimeout: time.Duration(c.conf.Timeout) * time.Second,
|
||||||
TLSHandshakeTimeout: time.Duration(c.conf.Timeout) * time.Second,
|
TLSHandshakeTimeout: time.Duration(c.conf.Timeout) * time.Second,
|
||||||
}
|
}
|
||||||
|
if c.conf.NoIPv6 {
|
||||||
|
c.httpTransport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
if strings.HasPrefix(network, "tcp") {
|
||||||
|
network = "tcp4"
|
||||||
|
}
|
||||||
|
return dialer.DialContext(ctx, network, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
err := http2.ConfigureTransport(c.httpTransport)
|
err := http2.ConfigureTransport(c.httpTransport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -150,6 +163,7 @@ func (c *Client) newHTTPClient() error {
|
|||||||
Transport: c.httpTransport,
|
Transport: c.httpTransport,
|
||||||
Jar: c.cookieJar,
|
Jar: c.cookieJar,
|
||||||
}
|
}
|
||||||
|
c.httpClientLastCreate = time.Now()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type config struct {
|
|||||||
Timeout uint `toml:"timeout"`
|
Timeout uint `toml:"timeout"`
|
||||||
NoCookies bool `toml:"no_cookies"`
|
NoCookies bool `toml:"no_cookies"`
|
||||||
NoECS bool `toml:"no_ecs"`
|
NoECS bool `toml:"no_ecs"`
|
||||||
|
NoIPv6 bool `toml:"no_ipv6"`
|
||||||
Verbose bool `toml:"verbose"`
|
Verbose bool `toml:"verbose"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,5 +65,13 @@ no_cookies = false
|
|||||||
# the same configuration as most public DNS servers.
|
# the same configuration as most public DNS servers.
|
||||||
no_ecs = false
|
no_ecs = false
|
||||||
|
|
||||||
|
# Disable IPv6 when querying upstream
|
||||||
|
#
|
||||||
|
# Only enable this if you really have trouble connecting.
|
||||||
|
# Doh-client uses both IPv4 and IPv6 by default and should not have problems
|
||||||
|
# with an IPv4-only environment.
|
||||||
|
# Note that DNS listening and bootstrapping is not controlled by this option.
|
||||||
|
no_ipv6 = false
|
||||||
|
|
||||||
# Enable logging
|
# Enable logging
|
||||||
verbose = false
|
verbose = false
|
||||||
|
|||||||
@@ -24,6 +24,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VERSION = "1.3.4"
|
VERSION = "1.3.6"
|
||||||
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)"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,6 +24,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VERSION = "1.3.4"
|
VERSION = "1.3.6"
|
||||||
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)"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<string>org.eu.starlab.doh.client</string>
|
<string>org.eu.starlab.doh.client</string>
|
||||||
<key>ProgramArguments</key>
|
<key>ProgramArguments</key>
|
||||||
<array>
|
<array>
|
||||||
|
<string>/usr/local/bin/doh-logger</string>
|
||||||
|
<string>doh-client</string>
|
||||||
<string>/usr/local/bin/doh-client</string>
|
<string>/usr/local/bin/doh-client</string>
|
||||||
<string>-conf</string>
|
<string>-conf</string>
|
||||||
<string>/usr/local/etc/dns-over-https/doh-client.conf</string>
|
<string>/usr/local/etc/dns-over-https/doh-client.conf</string>
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<string>org.eu.starlab.doh.server</string>
|
<string>org.eu.starlab.doh.server</string>
|
||||||
<key>ProgramArguments</key>
|
<key>ProgramArguments</key>
|
||||||
<array>
|
<array>
|
||||||
|
<string>/usr/local/bin/doh-logger</string>
|
||||||
|
<string>doh-server</string>
|
||||||
<string>/usr/local/bin/doh-server</string>
|
<string>/usr/local/bin/doh-server</string>
|
||||||
<string>-conf</string>
|
<string>-conf</string>
|
||||||
<string>/usr/local/etc/dns-over-https/doh-server.conf</string>
|
<string>/usr/local/etc/dns-over-https/doh-server.conf</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user