openssl 문서
SSL_get_error - OpenSSL Documentation
SSL_get_errorNAMESSL_get_error - obtain result code for TLS/SSL I/O operationSYNOPSIS#include int SSL_get_error(const SSL *ssl, int ret); DESCRIPTIONSSL_get_error() returns a result code (suitable for the C "switch" statement) for a preceding call to SSL_c
docs.openssl.org
openssl 라이브러리 에러확인 함수의 리턴값이 꽤 많아서 정리해봤다.
int SSL_get_error(const SSL *ssl, int ret);
SSL_get_error() 함수는 TLS/SSL I/O 작업을 수행한 스레드에서 사용해야 한다.
I/O 함수에서 반환된 값을 SSL_get_error() 함수의 ret 에 넣어줘야 한다.
괄호 안의 숫자는 리턴되는 int값이다. OS마다 다를수도 있음 주의.
- SSL_ERROR_NONE (0) : 성공. return > 0 일때만 반환됨
- SSL_ERROR_ZERO_RETURN (6): 상대가 TLS 연결 닫음(TCP가 닫혔다는 뜻은 아님). 정상종료로 더이상 SSL_read로 읽을 수 없음. SSL_OP_IGNORE_UNEXPECTED_EOF 옵션 켜져있으면 예상치 못한 EOF에서도 발생 가능함.
- SSL_ERROR_WANT_READ (2), SSL_ERROR_WANT_WRITE (3): READ나 WRITE작업이 완료되지 않음.
Read : nonblocking 일때 데이터가 복호화 하기에 부족하면 발생.
Write: nonblocking 일때 데이터를 다 쓰지 못하면 발생 (SSL버퍼->커널버퍼) - SSL_ERROR_WANT_CONNECT (7), SSL_ERROR_WANT_ACCEPT (8): nonblocking에서 연결 완료되지 않음
BIO_s_connect(), BIO_s_accept() 사용 시에만 발생. - SSL_ERROR_WANT_X509_LOOKUP (4): SSL_CTX_set_client_cert_cb()로 등록한 콜백이 나중에 다시 호출하라고 요청함.
- SSL_ERROR_WANT_ASYNC (9): 비동기 엔진이 아직 처리중. SSL_MODE_ASYNC 설정 시에만 발생.
- SSL_ERROR_WANT_ASYNC_JOB (10): async job pool이 가득 참. ASYNC_init_thread()로 제한 설정했을 경우
- SSL_ERROR_WANT_CLIENT_HELLO_CB (11): SSL_CTX_set_client_hello_cb() 콜백이 다시 호출 요청.
- SSL_ERROR_SYSCALL (5): 치명적 I/O오류 발생. 더이상 I/O하면 안됨. SSL_shutdown() 호출하면 안됨.
- SSL_ERROR_SSL (1): 라이브러리 내부 치명적 오류. 더이상 I/O하면 안됨. SSL_shutdown() 호출하면 안됨.
실제로 내가 쓸 에러코드는
WANT_READ
WANT_WRITE
ZERO_RETURN
이렇게 세가지정도로 보인다.
실제 클라이언트의 동작에 따라 서버에서는 어떤 에러코드가 뜨는지 확인해봤다.
다음은 c++ 코드는 Session클래스의 ProcessRead함수의 일부이다.
함수는 socket의 read event를 epoll로 감지한 뒤에 호출되며, 커널 버퍼의 데이터를 session의 readbuffer에 옮겨적는 역할.
SSL* ssl = _sslObject->GetSsl();
do {
int rd = SSL_read(ssl, _readBuffer.ReadPos(), READ_SIZE);
if (rd <= 0)
{
int err = SSL_get_error(ssl, rd);
if (err == SSL_ERROR_WANT_READ){//복호화 하기에 데이터 부족함.
return;
} else if (err == SSL_ERROR_ZERO_RETURN) {
// 상대가 close 함. SSL_shutdown ok
ProcessDisconnect(true);
return;
} else {//SSL에 심각한 에러 발생. SSL_shutdown 금지.
ProcessDisconnect(false);
return;
}
}
if (_readBuffer.OnWrite(rd) == false)
{
ProcessDisconnect(true);
return;
}
} while (SSL_has_pending(ssl));
실험에 사용한 클라이언트는 openssl과 내가 커스텀한 클라이언트였다.
openssl s_client -connect serverip:port
위는 openssl 클라이언트로 서버에 접속하는 명령어
- 클라이언트에서 ctrl + D 입력 (EOF 보내기)
SSL_ERROR_ZERO_RETURN 이 return된다. 이 경우는 SSL연결이 가장 아름답게 종료되는 경우로 그냥 소켓을 닫아주면 된다. - 클라이언트에서 ctrl + C 입력, kill 명령으로 클라이언트 종료 (EOF 없이 프로세스 종료)
SSL_ERROR_SYSCALL 이 return 된다. SSL_shutdown을 하면 안된다고 문서에 적혀있는데 호출해도 별 문제가 없었다.
그리고 이건 에러와는 관계없는데 서버측에서 먼저 SSL_shutdown을 호출했을 때 서버가 이를 무시하면 어떻게되는지 확인해봤다. 만약 close notify를 보내는데 성공했더라도 클라이언트측에서 close notify를 보내주지 않고, 소켓을 닫지도 않는다면 shutdown은 마무리되지 않는다. 이렇게되면 비정상 클라이언트 소켓이 fd를 차지하고 있기 때문에 좋지않다. 나는 이 문제를 해결하기 위해 timerfd를 설정하여 shutdown을 호출한 뒤에 3초후에도 아무런 통신이 오지 않으면 세션을 정리하도록 만들었다.
'공부 > CS' 카테고리의 다른 글
| SMTP로 이메일 보내기 with.C/C++ (0) | 2026.03.14 |
|---|---|
| SIGPIPE (0) | 2026.03.02 |
| 스레드 풀 thread pool (0) | 2026.02.24 |
| openssl example with.C/C++ (0) | 2026.02.23 |
| SSL/TLS 그리고 인증서란 무엇인가 (0) | 2026.02.23 |