【Golang】编译iOS版dnscrypt-proxy
本帖最后由 lichao 于 2023-4-2 15:45 编辑## 前言
  dnscrypt-proxy是一个开源github项目,用于加密dns请求,支持Win/Linux/MacOS/Android/iOS等平台,
官方却有iOS编译方法,但已经不兼容现有系统环境,因此笔者自行编译。项目地址<https://github.com/DNSCrypt/dnscrypt-proxy>
## 编译
和以往一样笔者位MacOS系统
1. 下载源码并进入dnscrypt-proxy/dnscrypt-proxy目录
2. 修改main.go,注意代码中包括了官方提到的防内存过高被杀进程的memorystatus_control,还有我自己发现的SIGURG的处理,此bug目前原因未知,进程启动没多久就会因为无法处理SIGURG而崩溃,google搜了下无所获,猜测是go的某个依赖库有问题,因此直接自己handle了该信号,可正常运行
```golang
package main
/*
#include <stdint.h>
int memorystatus_control(uint32_t command, int32_t pid, uint32_t flags, void *buffer, size_t buffersize);
*/
import "C"
import (
crypto_rand "crypto/rand"
"encoding/binary"
"flag"
"fmt"
"math/rand"
"os"
"os/signal"
"runtime"
"sync"
"syscall"
"github.com/jedisct1/dlog"
"github.com/kardianos/service"
)
const (
AppVersion = "2.1.4"
DefaultConfigFileName = "dnscrypt-proxy.toml"
)
type App struct {
wg sync.WaitGroup
quitchan struct{}
proxy *Proxy
flags *ConfigFlags
}
func handle_sigurg() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGURG)
go func() {
for s := range c {
switch s {
case syscall.SIGURG:
fmt.Println("SIGURG")
break
default:
break
}
}
}()
}
func main() {
handle_sigurg()
TimezoneSetup()
dlog.Init("dnscrypt-proxy", dlog.SeverityNotice, "DAEMON")
runtime.MemProfileRate = 0
seed := make([]byte, 8)
crypto_rand.Read(seed)
rand.Seed(int64(binary.LittleEndian.Uint64(seed[:])))
pwd, err := os.Getwd()
if err != nil {
dlog.Fatal("Unable to find the path to the current directory")
}
svcFlag := flag.String("service", "", fmt.Sprintf("Control the system service: %q", service.ControlAction))
version := flag.Bool("version", false, "print current proxy version")
flags := ConfigFlags{}
flags.Resolve = flag.String("resolve", "", "resolve a DNS name (string can be <name> or <name>,<resolver address>)")
flags.List = flag.Bool("list", false, "print the list of available resolvers for the enabled filters")
flags.ListAll = flag.Bool("list-all", false, "print the complete list of available resolvers, ignoring filters")
flags.JSONOutput = flag.Bool("json", false, "output list as JSON")
flags.Check = flag.Bool("check", false, "check the configuration file and exit")
flags.ConfigFile = flag.String("config", DefaultConfigFileName, "Path to the configuration file")
flags.Child = flag.Bool("child", false, "Invokes program as a child process")
flags.NetprobeTimeoutOverride = flag.Int("netprobe-timeout", 60, "Override the netprobe timeout")
flags.ShowCerts = flag.Bool("show-certs", false, "print DoH certificate chain hashes")
flag.Parse()
if *version {
fmt.Println(AppVersion)
os.Exit(0)
}
if os.Getuid() == 0 {
var MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT C.uint = 6;
if C.memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, C.int(os.Getpid()), 0, nil, 0) != 0 {
dlog.Warn("Failed to disable iOS launchd's memory restrictions; loading a large blacklist, for example, may cause dnscrypt-proxy to be killed!")
}
}
app := &App{
flags: &flags,
}
svcConfig := &service.Config{
Name: "dnscrypt-proxy",
DisplayName: "DNSCrypt client proxy",
Description: "Encrypted/authenticated DNS proxy",
WorkingDirectory: pwd,
Arguments: []string{"-config", *flags.ConfigFile},
}
svc, err := service.New(app, svcConfig)
if err != nil {
svc = nil
dlog.Debug(err)
}
app.proxy = NewProxy()
_ = ServiceManagerStartNotify()
if len(*svcFlag) != 0 {
if svc == nil {
dlog.Fatal("Built-in service installation is not supported on this platform")
}
if err := service.Control(svc, *svcFlag); err != nil {
dlog.Fatal(err)
}
if *svcFlag == "install" {
dlog.Notice("Installed as a service. Use `-service start` to start")
} else if *svcFlag == "uninstall" {
dlog.Notice("Service uninstalled")
} else if *svcFlag == "start" {
dlog.Notice("Service started")
} else if *svcFlag == "stop" {
dlog.Notice("Service stopped")
} else if *svcFlag == "restart" {
dlog.Notice("Service restarted")
}
return
}
if svc != nil {
if err := svc.Run(); err != nil {
dlog.Fatal(err)
}
} else {
app.Start(nil)
}
}
func (app *App) Start(service service.Service) error {
if service != nil {
go func() {
app.AppMain()
}()
} else {
app.AppMain()
}
return nil
}
func (app *App) AppMain() {
if err := ConfigLoad(app.proxy, app.flags); err != nil {
dlog.Fatal(err)
}
if err := PidFileCreate(); err != nil {
dlog.Criticalf("Unable to create the PID file: %v", err)
}
if err := app.proxy.InitPluginsGlobals(); err != nil {
dlog.Fatal(err)
}
app.quit = make(chan struct{})
app.wg.Add(1)
app.proxy.StartProxy()
runtime.GC()
<-app.quit
dlog.Notice("Quit signal received...")
app.wg.Done()
}
func (app *App) Stop(service service.Service) error {
PidFileRemove()
dlog.Notice("Stopped.")
return nil
}
```
3. 如官方说明添加dnscrypt-proxy.plist
```plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>get-task-allow</key>
<true/>
<key>proc_info-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>com.apple.private.network.reserved-port</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.developer.networking.networkextension</key>
<true/>
<key>com.apple.network.multipath-tcp</key>
<true/>
<key>platform-application</key>
<true/>
<key>com.apple.private.security.container-required</key>
<false/>
</dict>
</plist>
```
4. 添加build.sh如下
```bash
#!/bin/bash
export GOROOT=$(go env GOROOT)
CGO_ENABLED=1 GOOS=ios GOARCH=arm64 CC="$GOROOT/misc/ios/clangwrap.sh" CXX="$GOROOT/misc/ios/clangwrap.sh" \
CGO_CFLAGS="-isysroot $(xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=9.0 -fembed-bitcode -arch arm64" \
CGO_CXXFLAGS="-isysroot $(xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=9.0 -fembed-bitcode -arch arm64" \
CGO_LDFLAGS="-isysroot $(xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=9.0 -fembed-bitcode -arch arm64" \
go build -ldflags="-s -w" -tags=ios
ldid -Sdnscrypt-proxy.plist dnscrypt-proxy
```
5. 执行build.sh编译,得到dnscrypt-proxy,将文件example-dnscrypt-proxy.toml改为dnscrypt-proxy.toml,一起传入iPhone做测试
```bash
/usr/bin/dnscrypt-proxy -config /etc/dnscrypt-proxy/dnscrypt-proxy.toml -logfile /tmp/dnscrypt-proxy.log
```
可以看到运行正常:
```
dnscrypt-proxy 2.1.4
Network connectivity detected
Now listening to 127.0.0.1:53
Now listening to 127.0.0.1:53
Now listening to [::1]:53
Now listening to [::1]:53
Source loaded
Source loaded
Firefox workaround initialized
OK (DoH) - rtt: 316ms
OK (DNSCrypt) - rtt: 181ms
OK (DNSCrypt) - rtt: 183ms
OK (DNSCrypt) - rtt: 183ms - additional certificate
OK (DoH) - rtt: 309ms
OK (DNSCrypt) - rtt: 242ms
OK (DNSCrypt) - rtt: 214ms
OK (DoH) - rtt: 406ms
OK (DNSCrypt) - rtt: 259ms
OK (DNSCrypt) - rtt: 263ms
TIMEOUT
OK (DoH) - rtt: 1095ms
TIMEOUT
OK (DNSCrypt) - rtt: 253ms
OK (DNSCrypt) - rtt: 268ms
OK (DoH) - rtt: 394ms
OK (DoH) - rtt: 189ms
OK (DNSCrypt) - rtt: 311ms
OK (DNSCrypt) - rtt: 246ms
OK (DNSCrypt) - rtt: 289ms
OK (DoH) - rtt: 302ms
OK (DNSCrypt) - rtt: 248ms
OK (DNSCrypt) - rtt: 248ms - additional certificate
OK (DNSCrypt) - rtt: 261ms
OK (DNSCrypt) - rtt: 186ms
OK (DNSCrypt) - rtt: 215ms
OK (DNSCrypt) - rtt: 236ms
OK (DNSCrypt) - rtt: 224ms
OK (DNSCrypt) - rtt: 204ms
OK (DNSCrypt) - rtt: 314ms
OK (DNSCrypt) - rtt: 184ms
uses a non-standard provider name ('2.dnscrypt.unfiltered.ns1.adguard.com.' doesn't start with '2.dnscrypt-cert.')
OK (DNSCrypt) - rtt: 183ms
OK (DNSCrypt) - rtt: 185ms
OK (DoH) - rtt: 303ms
OK (DoH) - rtt: 302ms
OK (DNSCrypt) - rtt: 339ms
OK (DNSCrypt) - rtt: 241ms
OK (DNSCrypt) - rtt: 241ms - additional certificate
OK (DNSCrypt) - rtt: 235ms
OK (DNSCrypt) - rtt: 259ms
OK (DNSCrypt) - rtt: 203ms
OK (DoH) - rtt: 310ms
OK (DoH) - rtt: 270ms
OK (DoH) - rtt: 1083ms
TIMEOUT
OK (DNSCrypt) - rtt: 268ms
OK (DoH) - rtt: 301ms
OK (DNSCrypt) - rtt: 245ms
OK (DNSCrypt) - rtt: 245ms - additional certificate
System DNS configuration not usable yet, exceptionally resolving using bootstrap resolvers over tcp
OK (DoH) - rtt: 166ms
OK (DoH) - rtt: 249ms
OK (DNSCrypt) - rtt: 236ms
OK (DoH) - rtt: 267ms
OK (DoH) - rtt: 245ms
OK (DNSCrypt) - rtt: 284ms
OK (DNSCrypt) - rtt: 284ms - additional certificate
TIMEOUT
OK (DoH) - rtt: 295ms
OK (DNSCrypt) - rtt: 284ms
OK (DNSCrypt) - rtt: 116ms
OK (DoH) - rtt: 305ms
OK (DNSCrypt) - rtt: 92ms
TIMEOUT
OK (DoH) - rtt: 408ms
OK (DNSCrypt) - rtt: 246ms
OK (DNSCrypt) - rtt: 224ms
Sorted latencies:
- 92ms starrydns
- 116ms dct-ru1
- 166ms nextdns
- 181ms openinternet
- 183ms quad9-dnscrypt-ip4-nofilter-pri
- 183ms adguard-dns-unfiltered
- 184ms saldns01-conoha-ipv4
- 185ms faelix-ch-ipv4
- 186ms dnswarden-uncensor-dc-swiss
- 189ms cloudflare
- 203ms deffer-dns.au
- 204ms saldns03-conoha-ipv4
- 214ms scaleway-fr
- 215ms techsaviours.org-dnscrypt
- 224ms altername
- 224ms sth-dnscrypt-se
- 235ms dct-de1
- 236ms serbica
- 236ms faelix-uk-ipv4
- 241ms quad9-dnscrypt-ip4-nofilter-ecs-pri
- 242ms dnscrypt.ca-1
- 245ms plan9dns-fl
- 245ms plan9dns-nj-doh
- 246ms ams-dnscrypt-nl
- 246ms v.dnscrypt.uk-ipv4
- 248ms plan9dns-nj
- 249ms dnscrypt.ca-2-doh
- 253ms dct-nl1
- 259ms dct-at1
- 259ms ffmuc.net
- 261ms dnscrypt.uk-ipv4
- 263ms meganerd
- 267ms libredns
- 268ms scaleway-ams
- 268ms pryv8boi
- 270ms sth-doh-se
- 284ms plan9dns-mx
- 284ms dnscrypt.ca-2
- 289ms wevpn-singapore
- 295ms uncensoreddns-dk-ipv4
- 301ms plan9dns-mx-doh
- 302ms njalla-doh
- 302ms bortzmeyer
- 303ms dns.digitale-gesellschaft.ch
- 305ms dnscrypt.ca-1-doh
- 309ms meganerd-doh-ipv4
- 310ms uncensoreddns-ipv4
- 311ms wevpn-useast
- 314ms dnscrypt.pl
- 316ms dns.sb
- 339ms sby-limotelu
- 394ms dns.digitale-gesellschaft.ch-2
- 406ms dns.digitalsize.net
- 408ms doh-crypto-sx
-1083ms doh.appliedprivacy.net
-1095ms ams-doh-nl
Server with the lowest initial latency: starrydns (rtt: 92ms)
dnscrypt-proxy is ready - live servers: 56
```
此时使用nslookup测试dns服务器:
```bash
nslookup www.baidu.com 127.0.0.1
```
得到正确结果:
```
iPhone:~ root# nslookup www.baidu.com 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
www.a.shifen.com canonical name = www.wshifen.com.
Name: www.wshifen.com
Address: 45.113.192.101
Name: www.wshifen.com
Address: 45.113.192.102
```
下面就是打包为deb了,由于过程较为繁琐,笔者又比较懒就不写了。
实际使用时,需要在“系统设置-Wifi”里面设置DNS为127.0.0.1且删掉其他dns。即可生效,从此远离dns污染
非常不错
页:
[1]