Skip to content

Documentation about installing on Android #2269

@emanruse

Description

@emanruse

Here is my experience with 'dnscrypt-proxy' on Android (I use Replicant. Replicant has root and init.d support "out of the box".

To start off, I have spent more than a week digging the web for information on how to do it. I have read many many discussions, questions and answers (including issues here). The official documentation didn't really help. In the very beginning it says:

If you want to change the DNSCrypt resolver, unzip the downloaded archive, edit the RESOLVER_NAME variable in system/etc/init.d/99dnscrypt. Keep the content as a ZIP file, with the original structure.

I have downloaded and unzipped every single release since 2.0.6 (the first one introducing Android binaries). There is no 99dnscrypt in any of them. Neither there is such file in the source code in git. So, my next step was to search the web, read issues here and there, a lot of time and effort.

What I found:

  • @Quindecim's repo - it seems made for some software called Magisk. I don't want to install additional software which I don't need, give it permissions etc. I just want dnscrypt-proxy.
  • There are some solutions for creating a boot service using init.rc. This process seems to involve unpacking the boot image, editing init.rc, and repacking it. This is new to someone like me. I found several softwares/versions which unpack and repack but when testing unpacking and repacking with no modification whatsoever the repacked image is always quite smaller than the original. I decided not to risk bricking my phone, so I stopped exploring this route.
  • Researching further, I found this issue and from it - @uzen's repo. Unfortunately, it seems to include a binary with unknown source code in src/META-INF/com/google/android, so I won't run it. Instead of putting that blindly on my phone, I looked into the 99dnscrypt it includes and the two sub-scripts it calls. My impression: the author has spent quite some time on that. Shellcheck complains about so many problems though. Regardless of that, I decided to give these 3 scripts a try but unfortunately the result wasn't satisfactory. I couldn't get things to work as expected, so after many hours of digging into that obviusly old shell script code, I decided to return to simplicity and start from scratch.
  • Then I found this. The init.d script used by the questioner is pretty much the same one which I tried myself initially. The difference is that I don't get the errors he gets - there are no such selinux messages in my logcat.

The official documentation also suggests installing one of "four (paid) apps" to switch currently running DNS settings to DNSCrypt. That is another thing I don't want to do. Installing additional (especially non-free) software for the sake of improving security through a software like dnscrypt-proxy, thus increasing attack surface and so on, is a logical contradiction.

So, in my search for a simple, clean, and working FOSS solution I used the same steps as in the Stackexchange question. In my dnscrypt-proxy.toml I enable blocked_names and put only one line in it for testing:

*.fsf.org

My findings:

I notice that 'dnscrypt-proxy' is started twice on boot:

$ adb shell logcat | grep dns
12-29 19:25:23.100  1993  1993 I sysinit : Running /system/etc/init.d/99dnscrypt 
12-29 19:25:23.290  2006  2006 I dnscrypt: Starting dnscrypt-proxy... 
12-29 19:25:23.315  2010  2010 I dnscrypt: Changing dns with iptables... 
12-29 19:27:38.500  3459  3459 I sysinit : Running /system/etc/init.d/99dnscrypt 
12-29 19:27:38.550  3464  3464 I dnscrypt: Starting dnscrypt-proxy... 
12-29 19:27:38.595  3467  3467 I dnscrypt: Changing dns with iptables...

$ adb shell ps | grep dns
root      2009  1     813640 6500  futex_wait 40103db0 S dnscrypt-proxy
root      3466  1     808256 7628  futex_wait 4016fdb0 S dnscrypt-proxy

The 'iptables' rules are not applied:

root@i9300:/ # iptables -L | grep 53                                               
1|root@i9300:/ # iptables -t nat -L | grep 53                                      
1|root@i9300:/ # 

I kill 'dnscrypt-proxy' manually:

$ adb shell
root@i9300:/ # killall dnscrypt-proxy                                              
root@i9300:/ # killall dnscrypt-proxy                                              
killall: dnscrypt-proxy: No such process

Then I start the service manually (cellular data is not enabled):

root@i9300:/ # /etc/init.d/99dnscrypt                                            
root@i9300:/ # [2022-12-29 19:36:20] [NOTICE] dnscrypt-proxy 2.1.2
[2022-12-29 19:36:20] [NOTICE] Network not available yet -- waiting...

Now, 'logcat' and 'ps' show there is only one runnig process:

12-29 19:36:19.860  5209  5209 I dnscrypt: Starting dnscrypt-proxy... 
12-29 19:36:19.970  5213  5213 I dnscrypt: Changing dns with iptables...

$ adb shell ps | grep dns
root      5212  1     812096 7604  futex_wait 401c4db0 S dnscrypt-proxy

The firewall rule is applied correctly too:

root@i9300:/ # iptables -t nat -L | grep 53                                      
DNAT       udp  --  anywhere             anywhere             udp dpt:domain to:127.0.0.1:53

Enable cellular data and watch what is happening in 'adb shell':

root@i9300:/ # [2022-12-29 20:08:31] [NOTICE] Network connectivity detected
[2022-12-29 20:08:31] [NOTICE] Now listening to 127.0.0.1:53 [UDP]
[2022-12-29 20:08:31] [NOTICE] Now listening to 127.0.0.1:53 [TCP]
...
// many other regular notices
...
[2022-12-29 20:09:45] [NOTICE] dnscrypt-proxy is ready - live servers: 32

Everything seems to work. Testing to confirm:

root@i9300:/ # host fsf.org
host: Host not found.
1|root@i9300:/ # host gnu.org
gnu.org has address 209.51.188.116

So, the blocked_names section works and resolving works.

Next, I disabled cellular data, unplugged the USB cable connected to the computer and connected the external WiFi adapter (Replicant needs an external RYF adapter as the phone's built in one won't work without proprietary software). So, I could not test with ADB any more but only using the limited "Terminal" application in Replicant and using the browser that comes with Replicant (no idea what its name is).

In that terminal (rewriting manually here):

host -v fsf.org
host: Host not found.
host -v gnu.org
host: Host not found.

and so on - it seem nothing resolved.

In the browser I see a different result though:

  • fsf.org works (although it must not resolve)
  • gnu.org works
  • other sites work

Obviously, things don't work as expected when using WiFi.

Connecting the phone to the computer again I see that 'dnscrypt-proxy' process is still active. Re-testing with cellular data again shows the same result as above: fsf.org is not resolved, other domains are.

The questions are:

  1. Why only the logging commands of the init.d script work, considering that the script is ran by root at boot time?

  2. Why (even with manual starting of the service) the behavior is different when using WiFi?

  3. How to make this service work on boot with all connections (cellular, WiFi, reverse USB tethering, etc) without requiring manual starting through ADB or additional apps (assuming one already has root and init.d support)?

It would be really great if someone can update the documentation.

Best wishes for the new year!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions