티스토리 뷰

개발/gRPC

gRPC에 SSL/TLS 설정하기

아테즈 2019. 10. 4. 03:56

gRPC에 통신 암호화를 적용해보자!!

이번 프로젝트에서 서버 부분을 맡게 되었는데, gRPC를 써 볼 기회가 생겨서 공부한 후 사용하게 되었습니다.

 

먼저. gRPC에서 제공하는 Greeting Service의 예제 코드를 가지고 insecure한 통신을 하는 소스코드입니다

 

저는 gRPC python을 사용하고 있습니다.

 

TLS란?

TLS란, Transport Layer Security의 약자이며 통신 계층 보안을 담당하는 프로토콜입니다. SSL(Secure Socket Layer)에서 탄생한 기술이고 옛날에는 SSL이라고 불렸지만 지금은 TLS로 정식 명칭이 변경된 상태입니다.

 

인터넷을 사용해서 신뢰할 수 있는 통신을 하려면 통신 당사자(서버, 클라이언트)가 모두 신뢰할 수 있는 자임을 확인해야합니다. 그리고 통신 당사자의 통신 내용이 제 3자(패킷 스푸핑 등)의 공격에 의해 노출되지 않아야 합니다.

 

그래서 통신 도중에 여러 과정의 핸드셰이크(Handshake)를 하게 되고 이 과정에서 서버의 private key를 기반으로 만들어진 인증서가 필요합니다.

 

가끔 HTTPS와 TLS를  혼동하는데 TLS는 통신 프로토콜이고 HTTPS는 TLS 위에 HTTP를 얹은 HTTP 보안 통신 프로토콜입니다.

 

gRPC Python Server-Client간 TLS 프로토콜을 사용한 통신 구현하기

먼저, TLS가 붙어 있지 않은 소스 코드를 보겠습니다. (소스코드는 github의 grpc/example에서 가져왔습니다.)

 

greeting_client.py

import grpc
import helloworld_pb2

channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2.GreeterStub(channel)

greeting_server.py

class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

 

소스코드의 개선에 앞서, 여러가지 패키지 설치에 대해 말씀드릴 게 있습니다.

requirements.txt의 내용에도 포함 되지만, 저는 grpcio, grpcio-tools 패키지의 버젼을 지정해서 사용했습니다.

 

각각 grpcio~=1.19.0, grpcio-tools~=1.19.0 입니다.

다음 명령어를 사용해 설치하시면 되겠습니다.

$ pip3 install grpcio-tools~=1.19.0
$ pip3 install grpcio~=1.19.0

 

서버는 인증서가 자신이 발급한 인증서인지 확인하기 위해 자신의 private key와 인증서를 가지고 있어야 합니다.

그래서 다음 코드를 추가로 삽입하게 됩니다.

with open('private.key','rb') as f:
    private_key = f.read()

with open('certificate.crt', 'rb') as f:
    certificate_chain = f.read()

그 후, 이 두 정보를 이용해 서버의 credential을 만들게 됩니다.

 

server_credentials = grpc.ssl_server_credentials(
            ((private_key, certificate_chain,),))

TLS를 적용하지 않은 코드에서는 server.add_insecure_port를 사용했지만, 이젠 TLS를 적용한 secure port를 사용해야하므로 add_secure_port('{host}:{port}', credential) 함수를 사용해야합니다.

 

추가된 코드는 아래와 같습니다.

server.add_secure_port('[::]:9090', server_credentials)

 

이후에는 서버를 실행시켜주기만 하면 됩니다.

 

하지만, 아직 인증서를 만들지 않았기 때문에 실행해도 파일 읽기 에러가 날 것입니다.

 

인증서를 만들어보도록 합시다. 저는 ubuntu에서 작업해서 openssl이 설치되어 있었지만, windows나 타 OS에서 작업하시는 분들은 openssl이 설치되어 있는지 확인해 보도록 합시다.

 

OpenSSL을 이용해 private key, root certificate만들기

다음 명령어를 실행해보도록 합시다.

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt

이 명령어를 실행하면 private key (server.key) 하나와 root certificate (server.crt)가 생성됩니다. 인증서를 만드는데는 여러 정보가 필요하니 입력해주도록 합시다.

 

다만, 주의할 점은 다른 정보들은 관계 없지만 셀프 서명을 할때 CN(Common Name)localhost로 입력해주도록 합시다.

+2019.11.14 추가 ) local서버에서 테스트 할 때는 localhost로 CN을 정해주시는게 맞지만, 다른 곳(remote)에서 request를 보내실 때는 CN을 해당 서버의 DNS 도메인[예를 들어, atez.kagamine.me]으로 하셔야 합니다. localhost로 CN을 지정하신 후 인증서를 사용한다면 서버단에서 CN 검증 오류로 모든 요청을 거부합니다.

 

이렇게 만들어진 server.key 파일은 절대로 외부에 유출되어서는 안되는 private key입니다. 배포하실땐 server.crt만 배포하도록 합시다.

 

TLS통신을 하는 client.py

TLS통신을 하는 client의 소스코드를 secure_client.py라고 하겠습니다.

def main():
    host = 'localhost'
    port = ****(비공개)

    with open('server.crt', 'rb') as f:
        trusted_certs = grpc.ssl_channel_credentials(f.read())

    channel = grpc.secure_channel('localhost:****(비공개)', trusted_certs)
    
    stub = helloworld_pb2_grpc.GreeterStub(channel)
    response = stub.SayHello(helloworld_pb2.HelloRequest(name='ATEZ'))

    print("Greeter Client received: " + response.message)

기존의 client와는 달리 server에 연결할 때 인증서가 필요합니다. gRPC가 이런 점에서 편리한건 channel에 연결할 때만 인증서를 사용해주면 된다는 것입니다.

 

나머지 코드는 동일합니다.

 

grpc auth에 관한 sample code는 https://github.com/grpc/grpc/tree/v1.24.0/examples/python/auth 에 있습니다.

 

 

 

'개발 > gRPC' 카테고리의 다른 글

Docker Ubuntu에서 Python3.x 이미지 빌드하기  (0) 2019.10.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함