Since Android 9, Android by default only allows network connections over HTTPS. However the only requests i'm doing are done over the localhost (e.g http://10.41.199.226:port/FooBar
) which is handled by a
(C#)HttpListener
listening to that address:port combination.
Since this request is made over HTTP Android doesn't by default allow it. Following this documentation by Android about the network_security_config
file I can allow HTTP connections by adding the following network_security_config.xml
file
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
Which is called from the Android manifest using android:networkSecurityConfig="@xml/network_security_config"
.
This allows the HTTP request to be completed, however because this sets the base-config it allows HTTP requests to be made across the entire app. This isn't a good idea seeing I may want to add outgoing requests in the future, which I would want to be over HTTPS and would like this safety net to be in place for that. Making this a no-go.
Further on in that same document they introduce the domain-config
which allows you to set the cleartextTrafficPermitted
depending on the domain, which I tried with the following domains set
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
<domain includeSubdomains="true">10.0.0.1</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
With no results, requests were still getting blocked due to not being https.
I looked up the device's local address, and added it to the domains list
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.41.199.226</domain> <!--assume this is my local ip -->
</domain-config>
This worked, and HTTP was allowed only when requested over the localhost, while any outgoing request would this require HTTPS.
The only problem with this is is that I have no way of knowing the local ip off the device that'll run the app before the app is launched.
So my question is, is there a way to either:
localhost
as I tried, but which didn't work)includeSubdomains="true"
would do this for me when adding a 10.0.0.0
address. But it doesn't)network_security_config.xml
file at runtime, so I can dynamically update the domain name of one of the domain entries to the current local ip, when launching the app? The app is developed using Unity 2019.1.8 using the .net 4.x IL2CPP scripting runtime
The easy way to implement this is to use this attribute to your AndroidManifest.xml where you allow all http for all requests:
android:usesCleartextTraffic="true"
But in case you want some more configurations for different links for instance, allowing http for some domains but not other domains you must provide networkSecurityConfig
file.
To do this in Android 9 Pie you will have to set a networkSecurityConfig
in your Manifest application
tag like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>
Then in your xml folder you now have to create a file named network_security_config just like the way you have named it in the Manifest and from there the content of your file should be like this to enable all requests without encryptions:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
From there you are good to go. Now your app will make requests for all types of connections. For additional information on this topic https://developer.android.com/training/articles/security-config.