机构的方言止步于对外网关
한국어 원문으로 표시합니다.
한 줄 요약
대외계(FEP)는 은행 밖의 기관과 붙는 중계 계층이다. 기관마다 전문 규격·인증서·허용 주소가 다르고, 그 차이를 안쪽 시스템이 알지 않도록 한 곳(대외계)에 가두는 것이 이 계층의 존재 이유다. 안쪽은 LH-STD 표준만 알고, 대외계가 기관별 방언으로 번역하고, 기관별 신원(인증서)으로 붙는다.
왜 이게 필요했나
내부 시스템끼리는 표준을 정할 수 있다. LabHub 은행 안에서는 모두가 LH-STD 헤더를 쓴다. 그런데 타행·신용정보사·카드사·보험사는 각자의 규격을 가지고 있고, 우리에게 맞춰 주지 않는다. 어떤 기관은 전문길이가 자기 자신을 포함하고, 어떤 기관은 JSON 을 HTTPS 로 받고, 어떤 기관은 응답코드가 두 자리다. 이 차이를 계정계가 직접 다루기 시작하면 기관이 하나 늘 때마다 원장 시스템을 고친다.
보안의 무게도 다르다. 내부망은 우리가 통제하지만, 대외 구간은 남의 망과 이어진다. 그래서 대외 연동은 거의 언제나 상호 인증이다 — 우리가 기관 서버를 확인하는 것과 똑같이, 기관도 우리가 누구인지 인증서로 확인한다. 들어오는 쪽도 마찬가지로, 약속된 기관의 주소에서 온 연결만 받는다. 인증서는 기관마다 따로 발급받고, 만료일이 제각각이고, 교체 절차도 제각각이다. 이 모든 것을 한 곳에서 관리하지 않으면 어느 날 한 기관의 인증서가 조용히 만료되고, 그 기관과의 거래가 전부 멈춘다.
어떻게 동작하나
상호 TLS(mTLS). TLS 1.3(RFC 8446)에서 서버는 핸드셰이크 중 CertificateRequest 를 보내 클라이언트 인증서를 요구할 수 있다. 클라이언트는 자기 인증서와, 그 인증서의 개인키로 핸드셰이크 내용에 서명한 CertificateVerify 를 보낸다. 서버는 그 인증서가 자기가 믿는 CA 로 이어지는지 검증하고, 아니면 경고(alert)를 보내고 끊는다. 그래서 가람은행 CA 가 서명한 인증서로 한울신용정보에 붙으면 핸드셰이크 단계에서 거절된다. 반대로 우리도 기관 서버 인증서를 그 기관의 CA 로 검증한다 — 아무 인증서나 믿으면 중간자에게 거래를 넘긴다.
CSR 과 사설 CA. 기관 연동 인증서는 대개 공인 CA 가 아니라 기관이 운영하는 사설 CA 가 발급한다. 우리는 개인키를 만들고 그 공개키를 담은 인증서 서명 요청(CSR)을 보낸다. 개인키는 우리 밖으로 나가지 않는다. 기관이 서명해 돌려준 인증서에는 용도 확장(extendedKeyUsage)에 클라이언트 인증이 적힌다. 인증서 경로 검증과 유효 기간(notBefore·notAfter)은 X.509 프로파일인 RFC 5280 이 정한다 — 유효 기간 밖의 인증서는 검증에 실패한다.
기관 프로필. 기관마다 다른 값은 코드가 아니라 데이터로 둔다(2모듈의 라우팅 표와 같은 생각). 주소·포트, 형식(고정길이/JSON), 인코딩, 길이 기준, CA·인증서·개인키 경로, 허용 출발지 주소. 코드에는 기관 이름이 등장하지 않고, 프로필을 읽어 어댑터를 고른다. 새 기관은 프로필 한 줄과 어댑터 하나로 붙는다.
규격 번역. 안쪽의 표준 요청(JSON)을 받아 기관 규격으로 바꾸고, 기관 응답을 다시 표준으로 바꾼다. 이 코스의 가람은행은 전문길이가 자기 자신 4바이트를 포함한다. LH-STD 는 뺀다. 같은 104바이트 전문에 한쪽은 0104, 한쪽은 0100 을 쓴다. 이 차이를 틀리면 기관 서버는 길이만큼 읽고 남은 4바이트를 다음 전문으로 착각하거나, 모자란 4바이트를 기다리다 시간이 초과된다. 응답코드도 번역한다. 가람은행의 14(계좌 없음)는 안쪽에서 B202 다. 채널은 기관이 어디든 같은 코드를 본다.
들어오는 쪽의 두 겹. 기관이 우리에게 거는 연결은 방화벽이 1차로 걸러도, 애플리케이션이 한 번 더 출발지 주소를 확인한다. 방화벽 규칙은 다른 팀이 바꾸고, 대외계 프로필은 우리가 관리한다 — 한쪽이 실수해도 다른 쪽이 막게 두 겹으로. 허용 목록에 없는 주소는 한 바이트도 읽지 않고 끊고, 기록을 남긴다. 기록이 없으면 누가 두드렸는지 모른다.
만료 감시. 인증서의 notAfter 를 정기적으로 읽어 남은 일수가 기준보다 적으면 경고한다. 기관 인증서 교체에는 CSR 발송·서명·반영까지 몇 주가 걸리기도 하므로, 경고는 교체 기간보다 넉넉하게 먼저 울려야 한다.
현장에서 만나는 모습
대외 연동 장애의 단골은 셋이다. 첫째, 인증서 만료. 1년짜리 인증서를 개통 때 넣고 아무도 달력에 적지 않았다. 새벽에 한 기관과의 거래가 전부 핸드셰이크 오류로 멈추고, 로그에는 "certificate expired" 한 줄뿐이다. 둘째, 인증서 뒤바뀜. 기관이 여럿인데 인증서 파일 이름이 비슷해 교체 작업에서 다른 기관 인증서를 끼웠다 — 서버는 "unknown ca" 로 거절한다. 셋째, 규격 착각. 개발 때는 우리끼리 만든 모의 서버로 시험해 통과했는데, 개통 날 실제 기관이 길이 기준이 달라 첫 전문부터 형식 오류를 돌려준다. 정의서의 한 줄을 모의 서버가 다르게 흉내 낸 것이다. 그래서 대외 연동은 기관이 제공하는 시험 환경에서 기관의 서버로 확인한다.
다음 실습에서 할 것
두 기관(가람은행 201, 한울신용정보 301)의 사설 CA 를 픽스처로 만들고, 기관마다 키와 CSR 을 만들어 서명받는다. 기관 프로필을 쓰고, 가람은행과 상호 TLS 로 연결을 확인하고, 인증서를 바꿔 끼우면 거절되는 것을 재현한다. 그다음 기관별로 인증서·형식을 골라 보내는 fepgw.py, 허용 주소에서만 받는 inbound.py, 만료를 감시하는 certcheck.py 를 만든다.