2

I am trying to establish a Socket connection to a self signed server.

In my gradle file I'm using the following:

implementation 'io.ktor:ktor-network:1.6.5'
implementation 'io.ktor:ktor-network-tls:1.6.5'

My code to establish the connection:

socketConnection = aSocket( ActorSelectorManager( Dispatchers.IO ))
    .tcp( ).connect( InetSocketAddress( "192.168.1.5", 8080 ))
    .tls( Dispatchers.IO )

Now I tired to trust the cert by adding

android:networkSecurityConfig="@xml/network_security_config"

to my AndroidManifest.xml in the application tag.

My network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">192.168.78.74</domain>
        <trust-anchors>
            <certificates src="@raw/my_cert"/>
        </trust-anchors>
    </domain-config>
</network-security-config>

when I run the application I get this error:

java.security.cert.CertificateException: Domain specific configurations require that hostname aware checkServerTrusted(X509Certificate[], String, String) is used
    at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:112)
    at io.ktor.network.tls.TLSClientHandshake.handleCertificatesAndKeys(TLSClientHandshake.kt:234)
    at io.ktor.network.tls.TLSClientHandshake.negotiate(TLSClientHandshake.kt:165)
    at io.ktor.network.tls.TLSClientHandshake$negotiate$1.invokeSuspend(Unknown Source:14)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220

1 Answers1

1

I am using ktor and wanted to monitor the traffic using proxy man

In order to solve the exception I had to add the proxy directly to the HttpClient and add a custom trustmanager that does not check the certificate

Only use this for development purposes..

val client = HttpClient(CIO) {
    engine {
        proxy = ProxyBuilder.http("http://PROXY_IP_HERE:PROXY_PORT_HERE/")
        https {
            trustManager = MyTrustManager(this)
        }
    }
}

class MyTrustManager(private val config: TLSConfigBuilder) : X509TrustManager {
    private val delegate = config.build().trustManager
    private val extensions = X509TrustManagerExtensions(delegate)

    override fun checkClientTrusted(certificates: Array<out X509Certificate>?, authType: String?) {}

    override fun checkServerTrusted(certificates: Array<out X509Certificate>?, authType: String?) {}

    override fun getAcceptedIssuers(): Array<X509Certificate> = delegate.acceptedIssuers
}

With the following network security config:

<network-security-config>
    <domain-config>
        <!-- Make sure your URL Server here -->
        <domain includeSubdomains="true">your_domain</domain>
        <trust-anchors>
            <certificates src="user"/>
            <certificates src="system"/>
        </trust-anchors>
    </domain-config>

    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
            <certificates src="system" />
        </trust-anchors>
    </debug-overrides>

    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>
jhetrifork
  • 11
  • 1