SSL이란

SSL(Secure Sockets Layer)은 암호화 기반 인터넷 보안 프로토콜입니다. 인터넷 통신의 개인정보 보호, 인증, 데이터 무결성을 보장하기 위해 Netscape가 1995년 처음으로 개발했습니다. SSL은 현재 사용 중인 TLS 암호화의 전신입니다.

 

TrustKit이란

TrustKit은 모든 iOS 10+, macOS 10.10+, tvOS 10+ 또는 watchOS 3+ 앱에서 SSL 공개 키 고정 및보고를 쉽게 배포 할 수있는 오픈 소스 프레임 워크입니다. Swift 및 Objective-C 앱을 모두 지원합니다.

수동으로 고정을 구성하는 것은 어렵고 시간이 많이 소요될 수 있습니다. TrusKit 은 코드 몇 줄만 작성 하여 인증서의 공개 키 를 확인 하는 매우 쉬운 방법 을 제공하고 추가 기능도 제공합니다.

https://github.com/datatheorem/TrustKit

https://github.com/datatheorem/TrustKit/blob/master/docs/getting-started.md

 

적용하기

1.인증서 다운로드

브라우저에서 사이트 인증서 다운로드 

 

2.인증서로부터 pin추출

https://github.com/datatheorem/TrustKit/blob/master/get_pin_from_certificate.py

python 소스 다운로드 후

 

Pin 추출 : U3xTWXJOd447ON2zOz9w35qNaPAJDpqlFO4Jt/443us= 

$ python3 get_pin_from_certificate.py --type DER \*.google.com.cer
CERTIFICATE INFO
----------------
b'subject= /C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.google.com\nissuer= /C=US/O=Google Trust Services/CN=GTS CA 1O1\nSHA1 Fingerprint=E4:89:43:D9:6A:40:D5:34:B9:33:7E:E5:ED:A9:76:D2:20:1D:2E:BF\n'

TRUSTKIT CONFIGURATION
----------------------
kTSKPublicKeyHashes: @[@"b'U3xTWXJOd447ON2zOz9w35qNaPAJDpqlFO4Jt/443us='"] // You will also need to configure a backup pin

 

3.프로젝트에 TrustKit적용

pod 'TrustKit'
$ pod install

 

AppDelegate.swift

도메인 설정과 추출한 정보를 kTSKPublicKeyHashes값으로 설정

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        TrustKit.setLoggerBlock { (message) in
              print("TrustKit log: \(message)")
        }
        let trustKitConfig: [String: Any] = [
             kTSKSwizzleNetworkDelegates: false,
             kTSKPinnedDomains: [
                    "www.google.com": [
                           kTSKEnforcePinning: false,
                           kTSKIncludeSubdomains: true,
                           kTSKPublicKeyHashes: [
        //First public key -> Obtained from the Python script
        "U3xTWXJOd447ON2zOz9w35qNaPAJDpqlFO4Jt/443us=",
        //Second public key in case of the first one will expire
        "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
           ],
           kTSKReportUris:        ["https://overmind.datatheorem.com/trustkit/report"],
         ]
        ]]
        TrustKit.initSharedInstance(withConfiguration: trustKitConfig)
        
        return true
    }

 

HomeViewController.swift

 

delegate: self를 통해 재정의한 urlSession이 호출 되도록 선언함 

lazy var session: URLSession = {
       URLSession(configuration: URLSessionConfiguration.ephemeral,
                  delegate: self,
                  delegateQueue: OperationQueue.main)
    }()
let task = session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
	guard let data = data else {
		completion(nil)
		return
	}
	let str = String(decoding: data, as: UTF8.self)
	print(str)
})
task.resume()
extension HomeViewController: URLSessionDelegate {
    
    func urlSession(_ session: URLSession,
                    didReceive challenge: URLAuthenticationChallenge,
                    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
                                                
        if TrustKit.sharedInstance().pinningValidator.handle(challenge, completionHandler: completionHandler) == false {
            // TrustKit did not handle this challenge: perhaps it was not for server trust
            // or the domain was not pinned. Fall back to the default behavior
            completionHandler(.performDefaultHandling, nil)
        }
    }
}

URLSessionDelegate을 상속받아 urlSession에서 재정의하여 TrustKit을 통해 검증이 되도록 합니다. 

위와 같이 적용하여 정상적으로 동작하는 것을 확인합니다. 

https://certbot.eff.org/docs/index.html

docker를 활용해서 certbot으로 무료 인증서를 발급아서 적용해 보도록 하겠습니다.

certbot 의 manual 기능을 이용하여 서버외 다른 pc에서 인증서를 발급받기 위하여

dns서버에서 txt값으로 검증통해 발급을 받도록 합니다.

 

1.docker로 실행

- 인증서가 저장될 host 경로를 volume으로 설정

- domain을 입력합니다.

docker run -it --rm --name certbot   -v '[host_path]:/etc/letsencrypt'   -v '

[host_path]:/var/lib/letsencrypt'   certbot/certbot certonly -d '[domain]' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

 

2 설정화면

1. email설정

Saving debug log to /var/log/letsencrypt/letsencrypt.log

Plugins selected: Authenticator manual, Installer None

Enter email address (used for urgent renewal and security notices)

(Enter 'c' to cancel): [email]

 

2.동의

Please read the Terms of Service at

https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must

agree in order to register with the ACME server. Do you agree?

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(Y)es/(N)o: Y

 

3.동의

Would you be willing, once your first certificate is successfully issued, to

share your email address with the Electronic Frontier Foundation, a founding

partner of the Let's Encrypt project and the non-profit organization that

develops Certbot? We'd like to send you email about our work encrypting the web,

EFF news, campaigns, and ways to support digital freedom.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(Y)es/(N)o: Y

 

4.dns txt 설정 hash값 확인

Please deploy a DNS TXT record under the name

_acme-challenge.lottois.info with the following value:



qjbAHdtj.....



Before continuing, verify the record is deployed.

 

5.4번에서 value값을 dns 서버 TXT값으로 입력을 합니다.

6. dig 명령으로 전파가 되었는지 확인해 봅니다.

$ dig -t txt _acme-challenge.[domain]


; <<>> DiG 9.10.6 <<>> -t txt _acme-challenge.[domain]

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28324

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1



;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 1232

;; QUESTION SECTION:

;_acme-challenge.[domain]. IN TXT



;; ANSWER SECTION:

_acme-challenge.[domain]. 86400 IN TXT "qjbAHdtj_...."



;; Query time: 93 msec

;; SERVER: 1.1.1.1#53(1.1.1.1)

;; WHEN: Mon Dec 14 13:18:50 KST 2020

;; MSG SIZE rcvd: 113

 

7.확인후 Enter

Press Enter to Continue

Waiting for verification...

Cleaning up challenges

Subscribe to the EFF mailing list (email: [email]).

We were unable to subscribe you the EFF mailing list because your e-mail address appears to be invalid. You can try again later by visiting https://act.eff.org.



IMPORTANT NOTES:

- Congratulations! Your certificate and chain have been saved at:

/etc/letsencrypt/live/lottois.info/fullchain.pem

Your key file has been saved at:

/etc/letsencrypt/live/lottois.info/privkey.pem

Your cert will expire on 2021-03-14. To obtain a new or tweaked

version of this certificate in the future, simply run certbot

again. To non-interactively renew *all* of your certificates, run

"certbot renew"

- If you like Certbot, please consider supporting our work by:



Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate

Donating to EFF: https://eff.org/donate-le

 

8.볼륨 지정 폴더 확인

 

privkey.pem 과 fullchainn.pem가 생성된 것을 확인할 수 있습니다. 

 

3.nginx 적용

위 정보를 nginx에 적용한 설정파일은 하기 fullchain.pem, privkey.pem파일을 활용하여

https로 적용되는것을 확인하였습니다.

http {
    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    server {
        listen 80;
        server_name lottois.info;
        return 301 https://$host$request_uri;    
    }
    
    server {
        listen 443 ssl;
        server_name lottois.info;
        ssl_certificate /etc/nginx/cert/fullchain.pem;
    	ssl_certificate_key /etc/nginx/cert/privkey.pem;
        
        ssl_session_cache shared:le_nginx_SSL:1m;
	    ssl_session_timeout 1440m;
	
	    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	    ssl_prefer_server_ciphers on;
	
	    ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS";
    
        location / {
            proxy_pass         http://lottoweb:8080;
        }    
    }
    
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

 

'DevOps' 카테고리의 다른 글

[Docker] 네트워크, 컨테이너간 통신  (0) 2020.12.12
[Docker] Dockerfile command  (0) 2020.11.20
[Docker] docker 주요 명령어  (0) 2020.11.20
[nginx] nginx 프록시 설정  (0) 2020.11.17

+ Recent posts