본문 바로가기
Languages

Android 네트워크 보안 및 network Security Config 설정

by lucidiz 2023. 3. 22.
반응형

 

Android

Android 앱 개발 시 네트워크 보안 설정은 다음과 같은 단계를 따릅니다:

1. 네트워크 보안 프로토콜 선택: Android에서는 HTTPS (TLS)를 사용하여 앱과 서버 간의 통신을 암호화하고 보호합니다. HTTPS는 Android에서 제공하는 기본적인 보안 프로토콜입니다.

2. 인증서 검증: HTTPS를 사용하여 통신을 암호화하면서도, 중간자 공격(MITM)을 방지하기 위해 서버의 인증서를 검증해야 합니다. 안드로이드에서는 보안 인증서 체크를 위해, 네트워크 보안 구성에 대한 설정이나 강제화 방법을 지원하는데, OkHttp, Volley, Retrofit 등과 같은 HTTP 클라이언트 라이브러리를 통해 간단히 구현할 수 있습니다.

3. 안드로이드 네트워크 보안 구성 설정: 안드로이드에서는, 네트워크 보안 구성을 통해 앱에서 특정 서버로의 통신에 대한 추가적인 제어가 가능합니다.

특정 호스트 이름, 인증서와 함께 SSL을 강제하는 방식으로 사용자가 직접 검증할 수 있습니다.
Android 9부터 추가된 Network Security Configuration(NCS)를 사용하여 앱에서 통신할 수 있는 도메인을 명시하고 특정 네트워크 보안 설정을 적용할 수 있습니다.

 

위와 같은 방식으로 안드로이드 앱 개발시에도 보안 설정을 진행하면, 앱이 안전하게 서버와 통신할 수 있습니다.

 

 

Android 앱 개발 시 네트워크 보안 설정 단계별로 상세히 설명을 하면 다음과 같습니다.

 

네트워크 보안 프로토콜인 HTTPS를 선택하고 인증서 검증은 우선 다음과 같이 설정 및 코드를 작성해야 합니다.

 

1. 안드로이드 매니페스트 파일에서 인터넷 권한을 추가합니다. 이 권한은 앱이 인터넷 연결을 사용할 수 있도록 허용합니다.

 

<uses-permission android:name="android.permission.INTERNET" />

 

2. HTTPS 프로토콜을 사용하여 통신하는 경우, SSL 인증서를 검증하는 코드를 작성합니다. 이를 위해 SSL Socket Factory를 구현하고, 이를 HTTP 클라이언트에 설정합니다. 이를 통해 앱이 인증서 검증을 수행하도록 하여 보안을 강화할 수 있습니다.

 

TrustManager[] trustManagers = new TrustManager[] {new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // 클라이언트 인증서 검증 로직
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // 서버 인증서 검증 로직
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0])
        .build();

3. SSL Pinning을 구현하여 인증서 검증을 더욱 강화할 수 있습니다. 이를 위해 인증서의 고유한 지문을 추출하고, 코드에 하드 코딩하여 앱이 항상 같은 인증서를 사용하도록 설정합니다. 이를 통해 중간자 공격을 방지할 수 있습니다.

 

 

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.cert);
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
} finally {
    caInput.close();
}
String certPin = "1234567890abcdef"; // 인증서 지문
byte[] pin = certPin.getBytes("UTF-8");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashedPin = digest.digest(pin);
String hexString = Base64.encodeToString(hashedPin, Base64.DEFAULT);

CertificatePinner certificatePinner = new CertificatePinner.Builder()
        .add("example.com", hexString)
        .build();

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .certificatePinner(certificatePinner)
        .build();

 

4. 네트워크 트래픽을 암호화하기 위해 HTTPS를 사용하는 것이 좋습니다. 이를 위해 SSL 인증서를 구매하고, 서버에 설치하면 됩니다.

 

그리고 마지막으로 안드로이드 네트워크 보안 구성 설정을 합니다. 

 

1. res 디렉토리 내에 network_security_config.xml 파일을 생성합니다.
2. network_security_config.xml 파일에서 네트워크 보안 규칙을 정의합니다. 예를 들어, 모든 트래픽을 HTTPS로 보호하도록 설정할 수 있습니다.

 

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
    <domain-config>
        <domain includeSubdomains="true">example.com</domain>
        <trust-anchors>
            <certificate src="@raw/cert" />
        </trust-anchors>
        <pin-set>
            <pin digest="SHA-256">1234567890abcdef</pin>
        </pin-set>
    </domain-config>
</network-security-config>

 

 

  • 'base-config' 태그에서 'cleartextTrafficPermitted' 속성을 'false'로 설정하여 HTTP 트래픽을 차단할 수 있습니다. 만약, HTTP 트래픽을 허용할 경우는 'true'로 설정하면 됩니다.
  • 'domain-config' 태그에서 도메인을 지정하고, 인증서를 검증하는 규칙을 정의할 수 있습니다. 위 예시에서는 'example.com' 도메인을 HTTPS로 보호하도록 설정하였습니다. 'trust-anchors' 태그에서는 시스템과 사용자 인증서를 사용하여 검증할 수 있습니다.
  • 'pin-set' 태그에서 SSL Pinning을 설정할 수 있습니다. 위 예시에서는 '1234567890abcdef'라는 인증서 지문을 사용하여 검증하도록 설정하였습니다.

 

3. 매니페스트 파일에서 Network Security Config를 적용합니다. 'application' 태그에서 'android:networkSecurityConfig' 속성을 'network_security_config.xml' 파일의 리소스 ID로 설정합니다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application
        ...
        android:networkSecurityConfig="@xml/network_security_config"
        ...>
        ...
    </application>
</manifest>

 

위와 같이 설정하면 앱에서 사용하는 네트워크 보안 규칙이 'network_security_config.xml' 파일에서 정의한 대로 적용됩니다.

 

반응형