Skip to content

Building dnscrypt proxy for jailbroken iOS

Frank Denis edited this page Dec 4, 2022 · 2 revisions

(DNSCloak from the App Store provides dnscrypt-proxy2 and it can be ran on a non-jailbroken device. You may consider it a better use of your time to look at that first. However, its dnscrypt-proxy binary only supports 64-bit devices.)

Things that should be pointed out:

  • This guide has only been tested with the following:

    • dnscrypt-proxy 2.0.19
    • macOS 10.14
    • Go 1.11.4
    • An old 32-bit jailbroken iPad 4 running iOS 10.3.3, with OpenSSH set up
  • I do not know if this works to successfully build dnscrypt-proxy for arm64.

  • I do not know anything about macOS/iOS or Go development, so take the contents of the page as you will.

  • gomobile can be used to create the binary too, but it's a hassle for the following reasons:

    • Unless you have an iOS developer certificate of some sort in the Keychain, gomobile will not create the .app bundle and will discard the built dnscrypt-proxy binary
    • It combines dnscrypt-proxy builds for arm, arm64, 386 and x64_64 into one large 36MB binary - lipo is needed

    (Should you choose to use gomobile, however, it is pretty easy. If you don't have a cert added, create a dummy iOS project in Xcode, point it to your Apple account and build. Then, only export GOPATH and run something like gomobile build -target=ios -bundleid x. You'll find the dnscrypt binary inside dnscrypt-proxy.app/main.)

Installing needed programs

  1. Install XCode from the App Store. Run it after installation so that it can make system changes as necessary

  2. Install the Xcode Command Line Tools

  3. Install Go

Building a binary

  1. Perform the steps in Building from source up to step 4. You should be inside the dnscrypt-proxy-src folder with a clone of the dnscrypt-proxy source.

  2. Export the necessary variables (courtesy of gomobile):

# For 32-bit:
export GOARCH=arm
export GOARM=7
export CGO_CFLAGS="-miphoneos-version-min=6.1 -isysroot "$(xcrun --sdk iphoneos --show-sdk-path)" -arch armv7"

# For 64-bit (not tested):
export GOARCH=arm64
export CGO_CFLAGS="-isysroot "$(xcrun --sdk iphoneos --show-sdk-path)" -arch arm64"

# Common:
export GOPATH=$PWD
export GOOS=darwin
export CGO_ENABLED=1
export CC="$(xcrun --sdk iphoneos --find clang)"
export CXX="${CC}++"
export CGO_CXXFLAGS="${CGO_CFLAGS}"
export CGO_LDFLAGS="${CGO_CFLAGS}"
  1. As per Building from source, perform preparation:
cd src/dnscrypt-proxy
go clean
  1. Removing the memory limit (optional)

When dnscrypt-proxy is started via launchd, the amount of memory it can use is limited. If dnscrypt-proxy is configured to load a "large" blacklist (a 533KB file was enough to see this in practice), it will be killed when started via launchd.

git apply the following diff to have restrictions disabled:

diff --git a/dnscrypt-proxy/main.go b/dnscrypt-proxy/main.go
index b9c522e..81e0f39 100644
--- a/dnscrypt-proxy/main.go
+++ b/dnscrypt-proxy/main.go
@@ -1,5 +1,11 @@
 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 (
 	"flag"
 	"fmt"
@@ -29,6 +35,13 @@ func main() {
 	if err != nil {
 		dlog.Fatal("Unable to find the path to the current directory")
 	}
+	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!")
+		}
+	}
 	svcConfig := &service.Config{
 		Name:             "dnscrypt-proxy",
 		DisplayName:      "DNSCrypt client proxy",

  1. Start building:
go build -ldflags="-s -w" -o $GOPATH/$GOOS-$GOARCH/dnscrypt-proxy
  1. Place the dnscrypt-proxy binary onto the target iOS device

If all went well, $GOPATH/$GOOS-$GOARCH/dnscrypt-proxy should contain built dnscrypt-proxy for your device. scp etc. it over to the phone or tablet.

Adding entitlements

Before the binary can be ran on your iOS device, it needs to be signed. The following steps assume that they are being performed on the iOS device itself as root.

  1. Install ldid using Cydia or apt-get.

  2. Save the following (in UTF-8 as the first line points out) as ent.xml:

<?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>

NOTE: These entitlements are quite excessive. I do not know anything about entitlements. This suggests that only com.apple.private.security.container-required and platform-application are required, and that may be only for a certain case. DNSCloak's dnscrypt-proxy has no entitlements.

  1. Run ldid -Sent.xml dnscrypt-proxy (this assumes ent.xml and dnscrypt-proxy are in the same folder and that your current working directory is said folder)

Setting up dnscrypt-proxy

(Installation-macOS is quite applicable here too.)

  1. Move the binary into /usr/bin: mv dnscrypt-proxy /usr/bin/dnscrypt-proxy && chown root:wheel /usr/bin/dnscrypt-proxy && chmod 755 /usr/bin/dnscrypt-proxy

  2. Using a computer (or something like Safari and a file manager on the device if you prefer), download an archive containing the configuration files (like dnscrypt-proxy-macos-2.0.19.tar.gz). (Depending on how far master has deviated from the last release, you might need to get them from Git instead.)

  3. Save for the dnscrypt-proxy binary, extract the archive's contents to a folder somewhere. Copy example-dnscrypt-proxy.toml to dnscrypt-proxy.toml, and make the following changes:

  • perhaps uncomment tls_cipher_suite
  • set ignore_system_dns to true
  1. Choose where you want the dnscrypt-proxy configuration files to be stored. I scp'ed them into /etc/dnscrypt-proxy. Run the following to set appropriate permissions if using the suggested folder:
chown -R root:wheel /etc/dnscrypt-proxy
chmod 755 /etc/dnscrypt-proxy
chmod 644 /etc/dnscrypt-proxy/*
  1. cd to the configuration folder and run dnscrypt-proxy. If all goes well, stop it and run dnscrypt-proxy -service install and then start it like the output suggests.

  2. Finally, configure the DNS server for your Wi-Fi connection to be 127.0.0.1 inside the iDevice's settings.

If all went well, dnscrypt-proxy should start at boot (or when your semi-tethered jailbreak is activated if that's the case).

Clone this wiki locally