ossrs / srs

SRS is a simple, high-efficiency, real-time video server supporting RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH, and GB28181.
https://ossrs.io
MIT License
24.72k stars 5.28k forks source link

HTTPS: SSL errors in safari and chrome. #4036

Open suzp1984 opened 2 months ago

suzp1984 commented 2 months ago

Describe the bug There are a similar issue #3497, but I think it just fix part of problem.

start srs: ./objs/srs -c conf/https.srs.conf access: https://localhost:8088

  1. Safari browser access SRS https server. SRS error logs

    [2024-04-22 21:41:49.784][ERROR][9458][907848vt][0] serve error code=4043(HttpsRead)(Failed to read data from HTTPS stream) : parse message : parse message : grow buffer : read bytes : SSL_read r0=0, r1=6, r2=0, r3=1
    thread [9458][907848vt]: process_requests() [./src/app/srs_app_http_conn.cpp:185][errno=0]
    thread [9458][907848vt]: parse_message() [./src/protocol/srs_protocol_http_conn.cpp:103][errno=0]
    thread [9458][907848vt]: parse_message_imp() [./src/protocol/srs_protocol_http_conn.cpp:153][errno=0]
    thread [9458][907848vt]: grow() [./src/protocol/srs_protocol_stream.cpp:162][errno=0]
    thread [9458][907848vt]: read() [./src/app/srs_app_conn.cpp:947][errno=0]
  2. Chrome browser access SRS https server. SRS error logs

    [2024-04-22 21:43:25.057][INFO][9458][m46ggt66] TCP: before dispose resource(HttpsConn)(0x600002220000), conns=2, zombies=0, ign=0, inz=0, ind=0
    [2024-04-22 21:43:25.057][ERROR][9458][m46ggt66][0] serve error code=4042(HttpsHandshake)(Failed to do handshake for HTTPS) : start : handshake : handshake r0=-1, r1=1
    thread [9458][m46ggt66]: do_cycle() [./src/app/srs_app_http_conn.cpp:155][errno=0]
    thread [9458][m46ggt66]: on_start() [./src/app/srs_app_http_conn.cpp:388][errno=0]
    thread [9458][m46ggt66]: handshake() [./src/app/srs_app_conn.cpp:849][errno=0]
    [2024-04-22 21:43:25.057][INFO][9458][c0k5sp99] TCP: clear zombies=1 resources, conns=2, removing=0, unsubs=0
    [2024-04-22 21:43:25.057][INFO][9458][m46ggt66] TCP: disposing #0 resource(HttpsConn)(0x600002220000), conns=2, disposing=1, zombies=0
    [2024-04-22 21:43:25.057][INFO][9458][67y013a5] TCP: before dispose resource(HttpsConn)(0x6000022280f0), conns=1, zombies=0, ign=0, inz=0, ind=0
    [2024-04-22 21:43:25.057][ERROR][9458][67y013a5][0] serve error code=4042(HttpsHandshake)(Failed to do handshake for HTTPS) : start : handshake : handshake r0=-1, r1=1
    thread [9458][67y013a5]: do_cycle() [./src/app/srs_app_http_conn.cpp:155][errno=0]
    thread [9458][67y013a5]: on_start() [./src/app/srs_app_http_conn.cpp:388][errno=0]
    thread [9458][67y013a5]: handshake() [./src/app/srs_app_conn.cpp:849][errno=0]
    [2024-04-22 21:43:25.057][INFO][9458][c0k5sp99] TCP: clear zombies=1 resources, conns=1, removing=0, unsubs=0
    [2024-04-22 21:43:25.057][INFO][9458][67y013a5] TCP: disposing #0 resource(HttpsConn)(0x6000022280f0), conns=1, disposing=1, zombies=0
    [2024-04-22 21:43:25.062][INFO][9458][n904ay29] https: stream server done, use key ./conf/server.key and cert ./conf/server.crt, cost=3ms
    [2024-04-22 21:43:25.062][INFO][9458][n904ay29] HTTP #0 127.0.0.1:59812 GET https://localhost:8088/, content-length=-1
    [2024-04-22 21:43:25.063][INFO][9458][n904ay29] http match file=./objs/nginx/html/index.html, pattern=/, upath=/
    [2024-04-22 21:43:25.063][INFO][9458][n904ay29] TCP: before dispose resource(HttpsConn)(0x60000223c000), conns=1, zombies=0, ign=0, inz=0, ind=0
    [2024-04-22 21:43:25.063][WARN][9458][n904ay29][54] client disconnect peer. ret=1007

    Chrome will start 3 tcp connections to SRS, the first and second ssl handshake would be failed in srs_app_conn.cpp:849, the third ssl handshake would be success.

Version ALL SRS Version.

To Reproduce Steps to reproduce the behavior:

  1. start SRS: ./objs/srs -c conf/https.srs.conf (I used the srs's default SSL library: 3rdparty/openssl-1.1-fit)
  2. open https://localhost:8088/ in safari (macOS).
  3. the webpage can load well, but SRS has errors. (check error logs above).
  4. open https://localhost:8088/ in chrome.
  5. the webpage can load well, but SRS has errors. (check error logs above).

Expected behavior No SSL related exceptions.

Additional context Use Safari and Chrome to access https server, can have produce different errors, so I thinks It's not caused by self-signed certification.

Cause of Safari browser https://github.com/ossrs/srs/blob/5eb802dacac4e685989446e51d0ed5c594f86258/trunk/src/app/srs_app_conn.cpp#L911-L912 the log said: SSL_read r0=0, r1=6, r2=0, r3=1

r0 = 0, check the SSL_read doc: https://www.openssl.org/docs/man1.1.1/man3/SSL_read.html

<= 0 The read operation was not successful, because either the connection was closed, an error occurred or action must be taken by the calling process. Call SSL_get_error(3) with the return value ret to find out the reason.

r1 = 6, check the error 6 definition: https://github.com/ossrs/srs/blob/5eb802dacac4e685989446e51d0ed5c594f86258/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl.h#L1187

A workaround is to handle the SSL_ERROR_ZERO_RETURN:

if (r0 == 0 && r1 == SSL_ERROR_ZERO_RETURN) {
            if (nread) {
                *nread = 0;
            }
            return srs_error_new(ERROR_SOCKET_READ, "ssl read");;
 }

Cause of Chrome I guess the SSL handshake code maybe need to refined.

winlinvip commented 2 months ago

I would say it's a hard work to review the SSL API, because they are horrible documented. However, thank you for your nice work, even though I might not know when I will have time to look into this issue. I really don't like OpenSSL.