commit 63273630b325552be26a91ea402dacfed926a2df Author: huanglinhuan Date: Thu Oct 9 10:05:40 2025 +0800 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..36a389d --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +#编译 +##服务端编译命令 +g++ -o tls_server tls_server.cpp -lssl -lcrypto +./tls_server + +##客户端命令 +客户端运行在ue,使用Makefile交叉编译 + +运行实例: +# 1. 基本调试(推荐用于诊断延迟) +./tls_client.bin -h 183.238.13.170 -p 7271 -c client.crt -k client.key -x -d 1 + +# 2. 详细调试(查看SSL状态) +./tls_client.bin -h 183.238.13.170 -p 7271 -c client.crt -k client.key -x -d 2 + +# 3. 完整调试(查看所有消息) +./tls_client.bin -h 183.238.13.170 -p 7271 -c client.crt -k client.key -x -d 3 + +# 5. 循环测试10次,每次间隔2秒 +./tls_client.bin -h 183.238.13.170 -p 7271 -c client.crt -k client.key -x -t 3 -n 10 -i 2 \ No newline at end of file diff --git a/ca.crt b/ca.crt new file mode 100644 index 0000000..f88620e --- /dev/null +++ b/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDozCCAougAwIBAgIUPJ2ri4qd4BpnUcb/6vCZ//2uYd8wDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAOBgNVBAcMB0Jl +aWppbmcxDjAMBgNVBAoMBU15T3JnMQswCQYDVQQLDAJJVDERMA8GA1UEAwwITXlS +b290Q0EwHhcNMjUxMDA3MDYwMDI3WhcNMzUxMDA1MDYwMDI3WjBhMQswCQYDVQQG +EwJDTjEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEOMAwGA1UE +CgwFTXlPcmcxCzAJBgNVBAsMAklUMREwDwYDVQQDDAhNeVJvb3RDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMf0LkX1LF71yhsnqM4laww8B6RRo3nF +UD8pzGr4J8iFhtPyUr8T4Q3B1Et98sV+7zx4qxgYaMZ1IMX6QDti/T1qurAONhy9 +/HDGDrvMYE0AOQhvRvcqicpayqNqjLBJgdzh92Uei5s8F30tqLVm8tN715UaVDuc +enjh6s9e1GpR6CzvbKLEmsUESC9YFeV1kdlbn+b5cFgDElBan2nEpS2sAUamc5pt ++h8cjwojd58o3s+Cfc69DXnbSzRVo/7DSLO0itBLNvoo1YBSmJkuGDzsu0dcUD3m +84scYvxzvOZiUqESEaqXRMPw7OcOAQSbjloUgWfiX35ntmdeK5xyk90CAwEAAaNT +MFEwHQYDVR0OBBYEFH2YOXkKFAfeuB+IXTTB5NjXFsBqMB8GA1UdIwQYMBaAFH2Y +OXkKFAfeuB+IXTTB5NjXFsBqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAA7+FwMG6yJi9vDHdaFRWA/RFSTBCo5bcFJ7DO7DwvsEOfHnP5ygulDY +astft8RsGelVSlXJtWHaCdByST9V282q+P2Q2jjwfmVB5ATq2MAgobYsU3nwLg3r +c6zd34GeTJ6wjyGF5g3rDG8NqcHlARRwL8GbWX5lbcq9ooYLl9KHgFY+gz6u5njx +WyJdnCMLRUgTt5tsT/3k5PU2V9C5kwZh/eAocEsfhuXDplFHeqdvZTZaXD/oX+So +jPnLL6fsAoCskIhVVM0xGAXtWmhk+1LVtrqCfTQrqBhtXi5qCl3NLmBf+d0OClwh +HgkcqJYr+WaiEHLUyIdfZji/ZEml7aA= +-----END CERTIFICATE----- diff --git a/ca.key b/ca.key new file mode 100644 index 0000000..57b528a --- /dev/null +++ b/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDH9C5F9Sxe9cob +J6jOJWsMPAekUaN5xVA/Kcxq+CfIhYbT8lK/E+ENwdRLffLFfu88eKsYGGjGdSDF ++kA7Yv09arqwDjYcvfxwxg67zGBNADkIb0b3KonKWsqjaoywSYHc4fdlHoubPBd9 +Lai1ZvLTe9eVGlQ7nHp44erPXtRqUegs72yixJrFBEgvWBXldZHZW5/m+XBYAxJQ +Wp9pxKUtrAFGpnOabfofHI8KI3efKN7Pgn3OvQ1520s0VaP+w0iztIrQSzb6KNWA +UpiZLhg87LtHXFA95vOLHGL8c7zmYlKhEhGql0TD8OznDgEEm45aFIFn4l9+Z7Zn +XiuccpPdAgMBAAECggEAIXon7y2LxsBXHLHIqO8J26wHSYMjoCUheNnKMFSo8IEu +oDivku9EnFWJ8jO9nERS0KiRWMDpdeSxXoQ2EdtSc+B1LjnK5IgIhmcam2Wt7+Zs +JhXfZ013cWo/CBo0QOWluPIaRhNVo2Ftu1cUKn74g+D1qLCWTr61oJyOgDar0Lrn +Cf6DvZl5pGJVV3lQUiYNjZR5qEywpaMvVcVjRUaUElNplld9VLm9xE8lhwjq0GER +LQKt63p6b34kUKM8dS4cWr7+EutQPEwMLPtM/0HBUpid0qRIj5iZtROo86g8ksS1 +vzGQJ5asfgiRdZX7tkrj31RDg4latXQ8saHfZeOLzwKBgQDu0jI25NKHpxbWOveS +OBtZK12aiO4n/nria3YsOTGCWYqtFUsZqcfj7/C30KH0vKODNoy9933+5roEdOvc +FIo6PDUADiZNGN3Oy69EhBVuGr4OkK2LjjCSSI2jvWONTDN4lQ17nAiiJ0LMT/TX +CBIef0i/QpAOYeuUh8FT1Ph8DwKBgQDWVkIfGLXFGeRORjUBuVv0ceQMR1K8Nz0/ +ldR0nuwoxMReSgoP2OVlSXqiLWAC6zPuXxE8KBo7GkvxEc4+AcwcgPZoAkK0KGBO +BCyS6V45abp56nanAxgGZJ/BNd3MEma9rbraFjC/yF29heGeE0s+gR6uPMW32qJe +U8nBJFj1UwKBgCvxm3HEWwTA9w/GW+WY01duBlQ4G/JZ/gyJj34FrBl7FmxQvbfk +KLbFYLrB9fsNdtze/bi6wIFVvSayyO9/DAw5JdtzvxJyn+W8TuzBjRvsacpOTtCe +Akv4c6+MWrQWMGZgrtFu3ZvQs5bao4epoYPhEea3fcBXvjxfWnBtgKd7AoGAeTT8 +XWN230heEFmpfhkZRCnnwX3P7rn6O+v54h1BBWkIdx29hOquBtI/tFiek+f4TROb +xn4TH1smmOPt0qjniTLwpS6qFAFFPLklj8rCywrcNjd988JPIsZihTt1+wJo8Vi+ +crfbx4iCYjvEs8TLZ0RTWkrpsKfF7DvLuxpX6BsCgYBygdo3EGCuKlymw1V8xrWU +rumFLCqtTxUfTu4hzWpPM6wDBh6BNMOeXw8Z7bE69Ha8rWxGpu0qEgRM2RegNJza +f2j+hZUZbdJsGoClpq3ROBwBJHZ3ZUs+4po3JWQWc0DblaMOZftVIAh7EbMhmVPe +OwMin2eLv4aEzSEtSYK8aQ== +-----END PRIVATE KEY----- diff --git a/client.crt b/client.crt new file mode 100644 index 0000000..f0341d6 --- /dev/null +++ b/client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDTDCCAjQCFDcqUklN76USvOskALvfIUttDamKMA0GCSqGSIb3DQEBCwUAMGEx +CzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5n +MQ4wDAYDVQQKDAVNeU9yZzELMAkGA1UECwwCSVQxETAPBgNVBAMMCE15Um9vdENB +MB4XDTI1MTAwNzA2MDE1NFoXDTI2MTAwNzA2MDE1NFowZDELMAkGA1UEBhMCQ04x +EDAOBgNVBAgMB0JlaWppbmcxEDAOBgNVBAcMB0JlaWppbmcxDjAMBgNVBAoMBU15 +T3JnMQ8wDQYDVQQLDAZDbGllbnQxEDAOBgNVBAMMB2NsaWVudDEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaJLDgelGrpFYgFKqGUAvopUg709OHZjwT +FyEiBic7NgWWLSne5MFBMVY18nZF9khaJZn6wN//miubkb6hbP7695GERB/wVDTj +nMd9FjDaZvYoZQkxemjCBDpyYd5vfP7f83EkNEnD2VljBbRATfl7tXxcbELDHC9N +ukkFD/3sD8IiSpZyyO1U3Ljv/vuV4UCTadJlKB+R5hNqI7QWOr59bRQD2mykXGtx ++gf44rBXqfglhY2xevuvBHYvRncHARIjOvRUmf0ue3CHPtS6wafWiPoYz6Q92xa4 +xBDOtY9lrOZuwGzAsA0dRN80Uu2YmRUoe5bAnZiMk3iDBlt6dNafAgMBAAEwDQYJ +KoZIhvcNAQELBQADggEBAHV2eD8V79IF/u74mXjQxEalAJ0nA/ooMASbDIx08/wy +S4mwZl08yMFRHwV4nMp6kbRh81cWYtTe8+LW8w1mHUKd/7MzStKT93IADPULFjCi +4ee0wJmQePnWDxOcUUz6zEfh72W2Fy1CrZ99R0ZMF5ifUGUPNfmj0NsfqGgEReOO +ai3yNTEg0zg35+2SnHzodFerKWDeis5gP5EOURfHcKYKE3oEatxwn9//gb/sICoR +99rxHTO4BZB06DIArdxomZ84eanBkHGsJGuPjncR9fyLQcbP1SP0WUcR2p73xAd3 +EMBByvrT1m68g7L0SVqN05EshJoYWONb4gTHd2BCO0A= +-----END CERTIFICATE----- diff --git a/client.csr b/client.csr new file mode 100644 index 0000000..35cf19c --- /dev/null +++ b/client.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICqTCCAZECAQAwZDELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO +BgNVBAcMB0JlaWppbmcxDjAMBgNVBAoMBU15T3JnMQ8wDQYDVQQLDAZDbGllbnQx +EDAOBgNVBAMMB2NsaWVudDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCaJLDgelGrpFYgFKqGUAvopUg709OHZjwTFyEiBic7NgWWLSne5MFBMVY18nZF +9khaJZn6wN//miubkb6hbP7695GERB/wVDTjnMd9FjDaZvYoZQkxemjCBDpyYd5v +fP7f83EkNEnD2VljBbRATfl7tXxcbELDHC9NukkFD/3sD8IiSpZyyO1U3Ljv/vuV +4UCTadJlKB+R5hNqI7QWOr59bRQD2mykXGtx+gf44rBXqfglhY2xevuvBHYvRncH +ARIjOvRUmf0ue3CHPtS6wafWiPoYz6Q92xa4xBDOtY9lrOZuwGzAsA0dRN80Uu2Y +mRUoe5bAnZiMk3iDBlt6dNafAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAjnuL +FPH9DnQFg8yxNrD9XDDXGxrbRQEJqQeMJotLpafDk6Y8JROUrG9+v8p0KfdXn++6 +uZHAqsYMhTej6lK7ECI4RYt1vnmZ6V8Cwj/RaY+wqUVhx3UhDrcrbhjvf4YzZIQZ +ObcFsGc6qHfjKCENQvwPP7aKxyK9/mMGbXBDhT/8wACsYRh4HL/6Rr+Uad9n7q+j +y19s6h+SkkGST9feE4X4dWCx87w5us9QTRIywD4/L8IlzJXGEhZ285QxOokw/R7t +pQCkKksycajW7cu7kIZOsTus9wW2vyBhsfJnzTfZq8Qrqyt53C1d431Z8uD9yLMa +SfxqqgmsSUSLjfw3nA== +-----END CERTIFICATE REQUEST----- diff --git a/client.key b/client.key new file mode 100644 index 0000000..a72b547 --- /dev/null +++ b/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCaJLDgelGrpFYg +FKqGUAvopUg709OHZjwTFyEiBic7NgWWLSne5MFBMVY18nZF9khaJZn6wN//miub +kb6hbP7695GERB/wVDTjnMd9FjDaZvYoZQkxemjCBDpyYd5vfP7f83EkNEnD2Vlj +BbRATfl7tXxcbELDHC9NukkFD/3sD8IiSpZyyO1U3Ljv/vuV4UCTadJlKB+R5hNq +I7QWOr59bRQD2mykXGtx+gf44rBXqfglhY2xevuvBHYvRncHARIjOvRUmf0ue3CH +PtS6wafWiPoYz6Q92xa4xBDOtY9lrOZuwGzAsA0dRN80Uu2YmRUoe5bAnZiMk3iD +Blt6dNafAgMBAAECggEAHzak1qAOX7qEcjSdH1ugPbkSeoL3h6iNK7R4UiJ62UOk +N/fnTap289OgyIXTq3Emz5JjruJVubWndPY7awbeT0XIoscEzK7QkvLRdqQCuoc0 ++5MSHIHUKs2eZEErQNpH5mOumo04Dr+5mRKzoH3pskJa74BAuK/BaHT7ilnlqmJp +xoVDilQC5jiGys4MpCtx2Kt8l2CAlsE84vZff+PGV4O0kDsqqky6uhuJtrTaZs7j +bFJoWcG9L9s/WZtwb32X11epHOmQv6mrzgFyminzkBoCmO7cBNB44eyQJnnNYece +MnFdklKCPuSYc0lgWSepuUkrz8hLKC8+QzQO668UsQKBgQDYfmM9ES087q+H9ooc +l/GZsEdV/iN+Kcm1JkyyypzRQrmVUTyAp9SFRaLiQP3ea6Jy/CUeCC1SWwPLJM9E +EA0jlCYIPFOhsT7I1EM5Qa7DWf1z8bAVUMs1cqZrzOegIbEiKSu+Ym4MMVtvKvON +OqaTtwwNUvyxVHmsuZBUZzzXOQKBgQC2RZLvI4p/Qzbpznsmq4beCSFEACRJTa/F +e58/Xbmfdwo42WU17548k7sN/Jgyg7PVu4+bY5ZAYMibXFtEHW+sBz/4Gf90BZxE +egiKD7gtEw4kxu8BfygJgWyszK4guzTYKx+DJRl2xtvGCNX10SrV1rEfHvYNHXj8 +BekIht0ElwKBgQCb/FSch2fE42Vt3WEdwQy+45hCiV4hZRKEhxf0KrBaxmzY/TNO +r54ceFQoGRPR0lO17Z8AyHt/Pzy4fckpDTeqTvAoNu87LW5DXU0iUAUPlCNeCuII +ObJwzC7EtVqesifiqS9veZQ5DMcIjjX1qDClddolL4oKawdQQFORvODFYQKBgB/l +FM0b3wRd8qH/K7WclkEMP/HyRGc/XN6lvzwLXov0/KjuAbPqdjoLb9QGu2s7eKCR +7ZM3Xfdt+CyXgLDupbfonN0BT54xzSJ+aDgggA4DI5pz5SbR5WOkbivetSmtGJYr +FZyRRV9vdM22hho5u9EnfF8Bv/STj7QqJJkFYG+JAoGBAKx9evvrTS1tgcduIZXm +fFQJ/Y4r2AtUqPs5TE69wdQg+WL35Njd0r3gguK4isur4NV3Yb97JUN95L9E2cY2 +asRkLNGiWwgFtSp6xTA6ltfLbdW+smZgeFkMTu8O6WBUiep6TEkRiR60UnKxDfwO +eNr+BzEVtLNmY43pf3uRjnfm +-----END PRIVATE KEY----- diff --git a/client.p12 b/client.p12 new file mode 100644 index 0000000..d202ac3 Binary files /dev/null and b/client.p12 differ diff --git a/server.crt b/server.crt new file mode 100644 index 0000000..d39d0e0 --- /dev/null +++ b/server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUTCCAjkCFFDhJROu/swj7dMd1fokMaMYKNtfMA0GCSqGSIb3DQEBCwUAMGEx +CzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5n +MQ4wDAYDVQQKDAVNeU9yZzELMAkGA1UECwwCSVQxETAPBgNVBAMMCE15Um9vdENB +MB4XDTI1MTAwNzA2MDExN1oXDTI2MTAwNzA2MDExN1owaTELMAkGA1UEBhMCQ04x +EDAOBgNVBAgMB0JlaWppbmcxEDAOBgNVBAcMB0JlaWppbmcxDjAMBgNVBAoMBU15 +T3JnMQ8wDQYDVQQLDAZTZXJ2ZXIxFTATBgNVBAMMDG15c2VydmVyLmNvbTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPqMRUu5Vni7eAPEcstj2bfPOJXN +XtEvCLHH5XeVlmdUhwXZ9AlCITdjp2teV/hn6kbJACegY1g9IetnLqkWWm2MBvqm +OG9H2UfobSyfNiYmgI4X05KLlIzQ2vm2F0+sl5BQUv1t3ly4zXdb1q6O6xdiUaNG +d66DTL2MyaxCR8tgmhHiohEvozRzLUu63nbufva4CLALF71G45fq+jy+moIYeWop +SQn3Teu3HRTaV+XCMxCFw4TrJvN4aGDDHiE8f8TneSIISf8zEt4qGVzwSkOWTqZC +jkqe1vmV3qpMnfXdpsUYRXegKQjorIddWGBM86MisY3kFO9wmQjCggV0BssCAwEA +ATANBgkqhkiG9w0BAQsFAAOCAQEAKNIOPNNcZudVUq7ql16nnbBZrEkSF5WlMXZa +Zaka/Ix7/fuGJ2EKcy8npcPLOMSzt7DX9EmcIBF5FGrwBvLdrbR/ikW62vTgUv9q +l+P/VegPT6FXlU5AD5ur0hAYCsMk4EbT9ZfmU3qXDc55qXTQUY/dlzTOaCRBBQdO +PVImAdU/Zv3hKhXgj/93wWKdPFc3tjLiY3tqbMVJLkRaiQsR5tDVb8DQOXOgwWHf +PBdmrkLjYZHWk+wCinR50V9viS6KMXc/YJlDx1o5lfFdsMRWteDpHS4X01C7BF8R +vdJOr4sfVP8GRuFadW9GlEhRN4BKj/PecsZr+3HPUOHyfPesTw== +-----END CERTIFICATE----- diff --git a/server.csr b/server.csr new file mode 100644 index 0000000..a4696a4 --- /dev/null +++ b/server.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICrjCCAZYCAQAwaTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO +BgNVBAcMB0JlaWppbmcxDjAMBgNVBAoMBU15T3JnMQ8wDQYDVQQLDAZTZXJ2ZXIx +FTATBgNVBAMMDG15c2VydmVyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAPqMRUu5Vni7eAPEcstj2bfPOJXNXtEvCLHH5XeVlmdUhwXZ9AlCITdj +p2teV/hn6kbJACegY1g9IetnLqkWWm2MBvqmOG9H2UfobSyfNiYmgI4X05KLlIzQ +2vm2F0+sl5BQUv1t3ly4zXdb1q6O6xdiUaNGd66DTL2MyaxCR8tgmhHiohEvozRz +LUu63nbufva4CLALF71G45fq+jy+moIYeWopSQn3Teu3HRTaV+XCMxCFw4TrJvN4 +aGDDHiE8f8TneSIISf8zEt4qGVzwSkOWTqZCjkqe1vmV3qpMnfXdpsUYRXegKQjo +rIddWGBM86MisY3kFO9wmQjCggV0BssCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IB +AQCWDmyzIhCsrDKrOb7MVN6GJHIqQdZj88zxil0KSR7wxHXCZD2TOJXUnwEnQgW7 +m/q4375rpYO5bjhDr0JxnIsS0LB/QDZKMNA6PgR1LcTUZsQValvDnEVu/u1rQOgR +IZoVrGcKjfJ7rYPnArAPqhyLEtME6QYz7hzBeRdZhN+P1HQdBT5tpXi84awZmr5P +6MgKUS4HWui11sO/TRAL9AR2721PNN+ZwycPuPOuZ6YusI/6x3Y4u0OxxNPeOBme +LXt/kbpU1WNj2MemEnMLDMDB6COF86tJFw/cUF+lW5kBlvWIFWwapCp22h0XtxfE +zOaJgcmGkn2egLvmF5S3c/Tq +-----END CERTIFICATE REQUEST----- diff --git a/server.key b/server.key new file mode 100644 index 0000000..54fc562 --- /dev/null +++ b/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD6jEVLuVZ4u3gD +xHLLY9m3zziVzV7RLwixx+V3lZZnVIcF2fQJQiE3Y6drXlf4Z+pGyQAnoGNYPSHr +Zy6pFlptjAb6pjhvR9lH6G0snzYmJoCOF9OSi5SM0Nr5thdPrJeQUFL9bd5cuM13 +W9aujusXYlGjRneug0y9jMmsQkfLYJoR4qIRL6M0cy1Lut527n72uAiwCxe9RuOX +6vo8vpqCGHlqKUkJ903rtx0U2lflwjMQhcOE6ybzeGhgwx4hPH/E53kiCEn/MxLe +Khlc8EpDlk6mQo5Kntb5ld6qTJ313abFGEV3oCkI6KyHXVhgTPOjIrGN5BTvcJkI +woIFdAbLAgMBAAECggEAZ97zc5tY0CDYdqdg+BVjU6LjUKed4ZdgQWQgK92mRxxy +BekAFT6HStFTvV2VlvRt2f7Gw6boyNI/V7qlS5Bq2POuiQeUaf4dhIRFjrRK3LIl +pcMXAbBAW8jSn6fwLiXdiATlAxAjmck71XoLnL6/lCg8tDYos/7XN9ZAXdv0q8mE +1+nnyS6WfWXBdOqDhgfvzwyIG/dfA9KmXfHw3dFXQL9up9M18d4dQLC7XtYxlL9h +ttUG5XvzkwnnKbrNVKKFy1bynl335NrujyAQjWTVU9GmWTZvd11DFWXm0raQ1Q/Y +zS+JQ+rtJwldthN2vyCC5Oj5xZSCldVkivLqfpk/8QKBgQD98EDLtr2DGC5GwEEm +g+Gne45XocCc683Xq/WpTR45kuSv5rzb9G6zbWRgF9Rn6dYnkFgwlU4WW6bF851V +UWGOGoE4DL4F2ecvc/Bnmwp5v1aoDCokS2QEBRDg+Y5I769L1PdQwWVRs85TQv9s +9DqAXAwjZAJJlKAqEiLABAkJLwKBgQD8lPieQytn43hWZfm+IA4zNLg4Fuhd9NPz +IsYCYFno4F2Ibp7kspm0HTf1u4/pXGCEbDIxgY4EX2KVQfTuEovx0VMlgGVJVsYZ +Z0LMmMkDe/xRh9Pta0uI5ApP+kxw/hv7ug+r4jrBdFxacM8913Q24xn1sGPbMxcw +t6bF7gK9JQKBgQCAtQISfpfFVz81SwJ6hAOegOhfkDNxFa9qLdVArz6vjb1tTnTQ +wy5MsRhcABf/ZyzNNsMMNNC0UlXQJS7MbIgWn2Z5QzQZAR3FFm12BcYkeQ9x82B0 +ruWNiAfLD5HHc/yUYefMPYmeBJWB7AZMceko3/6i/XCPXM5lJHYKfsEZrwKBgQC2 +zAGaWDZju2Zt8ONry7s7J95jCYEl7nguMG5pbd3kAezvPk/UZ8WBatwDBblDRE29 +yKgS2BY15+pq5w8h9V4+piWssF2dVCWOYQMhGznvQZ38S3b/DnXeHluwQg9sfxs1 +dRS+ar3nIBVuhtIViYZb6sPw4bWDAFi6M0+JU5W72QKBgQD02Z8VHXtdKbzWafK6 +TOJ3u5ReTL78yF4JLdtLLpnOJ0XFpKbLRzCYrBIuLwJgnTC1VqcnVezlCvcDj8fc +KUNQbEAFDMUedA9J4tIsohjZlbW1tbyAo7h160TOUg+15CIMLpI+6Or5ADXeyisv +T68iyFB+Qul1Nr/J/8JlPRD6pw== +-----END PRIVATE KEY----- diff --git a/tls_client.c b/tls_client.c new file mode 100644 index 0000000..a7a2357 --- /dev/null +++ b/tls_client.c @@ -0,0 +1,970 @@ +/** + * @file tls_client.c + * @brief TLS 1.2/1.3 客户端实现 + * @author Assistant + * @date 2024 + * @version 1.0.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BUFFER_SIZE 4096 +#define TEST_DATA_SIZE 1024 +#define MAX_RETRIES 3 +#define CONNECT_TIMEOUT 10 + +// 全局SSL上下文 +SSL_CTX *ssl_ctx = NULL; + +/** + * @brief 格式化时间戳为易读格式 + */ +void print_timestamp(time_t timestamp) { + struct tm *tm_info; + char time_str[32]; + + tm_info = gmtime(×tamp); + strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S UTC", tm_info); + printf("[%s]", time_str); +} + +/** + * @brief SSL信息回调函数 + */ +void ssl_info_callback(const SSL *ssl, int type, int val) { + const char *str; + static time_t last_time = 0; + time_t current_time; + + // 检查SSL对象是否有效 + if (!ssl) { + printf("SSL回调: SSL对象为空\n"); + return; + } + + current_time = time(NULL); + + switch (type) { + case SSL_CB_LOOP: + str = SSL_state_string_long(ssl); + if (str) { + // 计算与上次状态的时间差 + if (last_time > 0) { + double time_diff = difftime(current_time, last_time); + if (time_diff > 0.5) { // 只显示超过0.5秒的延迟 + print_timestamp(current_time); + printf(" SSL状态: %s (延迟: %.1f秒)\n", str, time_diff); + } else { + print_timestamp(current_time); + printf(" SSL状态: %s\n", str); + } + } else { + print_timestamp(current_time); + printf(" SSL状态: %s\n", str); + } + last_time = current_time; + } + break; + case SSL_CB_ALERT: + str = SSL_alert_type_string_long(val); + if (str) { + print_timestamp(current_time); + printf(" SSL警告: %s\n", str); + } + break; + case SSL_CB_EXIT: + if (val == 0) { + str = SSL_state_string_long(ssl); + if (str) { + print_timestamp(current_time); + printf(" SSL退出: %s\n", str); + } + } else if (val < 0) { + str = SSL_state_string_long(ssl); + if (str) { + print_timestamp(current_time); + printf(" SSL错误: %s\n", str); + } + } + break; + case SSL_CB_HANDSHAKE_START: + print_timestamp(current_time); + printf(" SSL握手开始\n"); + last_time = current_time; + break; + case SSL_CB_HANDSHAKE_DONE: + print_timestamp(current_time); + printf(" SSL握手完成\n"); + break; + default: + // 过滤掉重复的4097类型回调 + if (type != 4097) { + print_timestamp(current_time); + printf(" SSL回调: 类型=%d, 值=%d\n", type, val); + } + break; + } +} + +/** + * @brief SSL消息回调函数 + */ +void ssl_msg_callback(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { + const char *direction = write_p ? "发送" : "接收"; + const char *content_name = ""; + time_t current_time; + + // 检查参数有效性 + if (!buf || len == 0) { + return; + } + + current_time = time(NULL); + + switch (content_type) { + case SSL3_RT_CHANGE_CIPHER_SPEC: + content_name = "ChangeCipherSpec"; + break; + case SSL3_RT_ALERT: + content_name = "Alert"; + break; + case SSL3_RT_HANDSHAKE: + content_name = "Handshake"; + break; + case SSL3_RT_APPLICATION_DATA: + content_name = "ApplicationData"; + break; + default: + content_name = "Unknown"; + break; + } + + // 只显示重要的握手消息,过滤掉重复的Unknown消息 + if (content_type == SSL3_RT_HANDSHAKE || content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + print_timestamp(current_time); + printf(" SSL消息: %s %s (版本: %d, 长度: %zu)\n", direction, content_name, version, len); + } +} + +/** + * @brief 初始化OpenSSL库 + * @param debug_level 调试级别 (0=无调试, 1=基本, 2=详细, 3=完整) + */ +void init_openssl(int debug_level) { + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + + if (debug_level > 0) { + // 启用OpenSSL调试 + if (debug_level >= 1) { + printf("启用OpenSSL基本调试\n"); + } + if (debug_level >= 2) { + printf("启用OpenSSL详细调试\n"); + } + if (debug_level >= 3) { + printf("启用OpenSSL完整调试\n"); + } + } +} + +/** + * @brief 清理OpenSSL资源 + */ +void cleanup_openssl() { + if (ssl_ctx) { + SSL_CTX_free(ssl_ctx); + } + EVP_cleanup(); + ERR_free_strings(); +} + +/** + * @brief 创建SSL上下文 + * @param cert_file 客户端证书文件路径 + * @param key_file 客户端私钥文件路径 + * @param ca_file CA证书文件路径 + * @param verify_peer 是否验证服务器证书 + * @param tls_version TLS版本 (1=TLS1.2, 2=TLS1.3, 0=自动) + * @return SSL_CTX* SSL上下文指针,失败返回NULL + */ +SSL_CTX* create_ssl_context(const char* cert_file, const char* key_file, const char* ca_file, int verify_peer, int tls_version, int debug_level) { + SSL_CTX *ctx; + + // 创建SSL上下文,支持TLS 1.2和1.3 + ctx = SSL_CTX_new(TLS_client_method()); + if (!ctx) { + fprintf(stderr, "无法创建SSL上下文\n"); + return NULL; + } + + // 设置调试回调(如果启用调试) + if (debug_level >= 2) { + SSL_CTX_set_info_callback(ctx, ssl_info_callback); + } + if (debug_level >= 3) { + SSL_CTX_set_msg_callback(ctx, ssl_msg_callback); + } + + // 根据指定版本设置TLS版本 + if (tls_version == 1) { + // 只使用TLS 1.2 + if (SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION) != 1 || + SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION) != 1) { + fprintf(stderr, "设置TLS 1.2版本失败\n"); + SSL_CTX_free(ctx); + return NULL; + } + printf("配置为TLS 1.2模式\n"); + } else if (tls_version == 2) { + // 只使用TLS 1.3 + if (SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION) != 1 || + SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION) != 1) { + fprintf(stderr, "设置TLS 1.3版本失败\n"); + SSL_CTX_free(ctx); + return NULL; + } + printf("配置为TLS 1.3模式\n"); + } else { + // 自动模式:支持TLS 1.2和1.3 + if (SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION) != 1) { + fprintf(stderr, "设置最小TLS版本失败\n"); + SSL_CTX_free(ctx); + return NULL; + } + + if (SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION) != 1) { + fprintf(stderr, "设置最大TLS版本失败\n"); + SSL_CTX_free(ctx); + return NULL; + } + printf("配置为TLS 1.2/1.3自动模式\n"); + } + + // 加载客户端证书 + printf("加载客户端证书: %s\n", cert_file); + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "加载客户端证书失败: %s\n", cert_file); + ERR_print_errors_fp(stderr); + SSL_CTX_free(ctx); + return NULL; + } + printf("客户端证书加载成功\n"); + + // 加载客户端私钥 + printf("加载客户端私钥: %s\n", key_file); + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "加载客户端私钥失败: %s\n", key_file); + ERR_print_errors_fp(stderr); + SSL_CTX_free(ctx); + return NULL; + } + printf("客户端私钥加载成功\n"); + + // 验证私钥与证书匹配 + printf("验证私钥与证书匹配...\n"); + if (SSL_CTX_check_private_key(ctx) != 1) { + fprintf(stderr, "私钥与证书不匹配\n"); + ERR_print_errors_fp(stderr); + SSL_CTX_free(ctx); + return NULL; + } + printf("私钥与证书匹配验证成功\n"); + + // 加载CA证书用于验证服务器证书 + if (ca_file && SSL_CTX_load_verify_locations(ctx, ca_file, NULL) != 1) { + fprintf(stderr, "加载CA证书失败: %s\n", ca_file); + SSL_CTX_free(ctx); + return NULL; + } + + // 设置验证模式 + if (verify_peer) { + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + } else { + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + printf("警告: 已禁用服务器证书验证\n"); + } + + // 设置验证深度 + SSL_CTX_set_verify_depth(ctx, 4); + + return ctx; +} + +/** + * @brief 创建TCP连接 + * @param hostname 服务器主机名 + * @param port 服务器端口 + * @return int 套接字文件描述符,失败返回-1 + */ +int create_tcp_connection(const char* hostname, int port) { + int sockfd; + struct sockaddr_in server_addr; + int opt = 1; + + // 创建套接字 + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("创建套接字失败"); + return -1; + } + + // 设置套接字选项,避免RST包问题 + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + perror("设置SO_REUSEADDR失败"); + close(sockfd); + return -1; + } + + // 设置TCP_NODELAY选项,减少延迟 + if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) { + perror("设置TCP_NODELAY失败"); + close(sockfd); + return -1; + } + + // 设置服务器地址 + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + + // 解析主机名 + if (inet_pton(AF_INET, hostname, &server_addr.sin_addr) <= 0) { + fprintf(stderr, "无效的IP地址: %s\n", hostname); + close(sockfd); + return -1; + } + + // 连接到服务器 + if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + perror("连接服务器失败"); + close(sockfd); + return -1; + } + + printf("成功连接到服务器 %s:%d\n", hostname, port); + return sockfd; +} + +/** + * @brief 执行TLS握手 + * @param ssl SSL连接对象 + * @return int 成功返回1,失败返回0 + */ +int perform_tls_handshake(SSL* ssl) { + int ret; + time_t start_time, end_time, step_time; + double handshake_time, step_duration; + + printf("开始TLS握手...\n"); + start_time = time(NULL); + step_time = start_time; + + // 设置握手超时 + int sockfd = SSL_get_fd(ssl); + if (sockfd > 0) { + struct timeval timeout; + timeout.tv_sec = 30; // 30秒超时 + timeout.tv_usec = 0; + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + printf("设置握手超时: 30秒\n"); + } + + // 执行SSL握手 + printf("正在执行SSL_connect()...\n"); + ret = SSL_connect(ssl); + + end_time = time(NULL); + handshake_time = difftime(end_time, start_time); + step_duration = difftime(end_time, step_time); + + printf("SSL_connect() 耗时: %.2f 秒\n", step_duration); + + if (ret != 1) { + int err = SSL_get_error(ssl, ret); + fprintf(stderr, "TLS握手失败,错误代码: %d\n", err); + + // 详细的错误诊断 + switch (err) { + case SSL_ERROR_SSL: + fprintf(stderr, "SSL协议错误,可能是证书验证失败\n"); + break; + case SSL_ERROR_SYSCALL: + fprintf(stderr, "系统调用错误\n"); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + fprintf(stderr, "需要更多数据\n"); + break; + default: + fprintf(stderr, "未知SSL错误\n"); + break; + } + + ERR_print_errors_fp(stderr); + + // 提供解决建议 + fprintf(stderr, "\n解决建议:\n"); + fprintf(stderr, "1. 使用 --no-verify 选项禁用证书验证\n"); + fprintf(stderr, "2. 检查服务器证书是否有效\n"); + fprintf(stderr, "3. 确保CA证书文件正确\n"); + fprintf(stderr, "4. 检查系统时间是否正确\n"); + + return 0; + } + + // 获取连接信息 + printf("TLS握手成功!\n"); + printf("握手耗时: %.2f 秒\n", handshake_time); + printf("协议版本: %s\n", SSL_get_version(ssl)); + printf("密码套件: %s\n", SSL_get_cipher(ssl)); + + // 验证服务器证书 + X509* cert = SSL_get_peer_certificate(ssl); + if (cert) { + printf("服务器证书验证成功\n"); + X509_free(cert); + } else { + printf("警告: 无法获取服务器证书\n"); + } + + return 1; +} + +/** + * @brief 发送测试数据 + * @param ssl SSL连接对象 + * @return int 成功返回1,失败返回0 + */ +int send_test_data(SSL* ssl) { + char test_data[TEST_DATA_SIZE]; + int bytes_sent; + time_t start_time, end_time; + double send_time; + + // 生成1KB测试数据 + for (int i = 0; i < TEST_DATA_SIZE; i++) { + test_data[i] = 'A' + (i % 26); + } + + printf("发送 %d 字节测试数据...\n", TEST_DATA_SIZE); + start_time = time(NULL); + + // 发送数据 + bytes_sent = SSL_write(ssl, test_data, TEST_DATA_SIZE); + + end_time = time(NULL); + send_time = difftime(end_time, start_time); + printf("SSL_write() 耗时: %.2f 秒\n", send_time); + + if (bytes_sent <= 0) { + int err = SSL_get_error(ssl, bytes_sent); + fprintf(stderr, "发送数据失败,错误代码: %d\n", err); + return 0; + } + + printf("成功发送 %d 字节数据\n", bytes_sent); + return 1; +} + +/** + * @brief 接收服务器响应 + * @param ssl SSL连接对象 + * @return int 成功返回1,失败返回0 + */ +int receive_response(SSL* ssl) { + char buffer[MAX_BUFFER_SIZE]; + int bytes_received; + time_t start_time, end_time; + double receive_time; + int timeout_seconds = 30; // 30秒超时 + + printf("等待服务器响应(超时: %d秒)...\n", timeout_seconds); + start_time = time(NULL); + + // 设置socket超时 + int sockfd = SSL_get_fd(ssl); + if (sockfd > 0) { + struct timeval timeout; + timeout.tv_sec = timeout_seconds; + timeout.tv_usec = 0; + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + } + + // 接收数据 + bytes_received = SSL_read(ssl, buffer, MAX_BUFFER_SIZE - 1); + + end_time = time(NULL); + receive_time = difftime(end_time, start_time); + printf("SSL_read() 耗时: %.2f 秒\n", receive_time); + + // 检查是否超时 + if (receive_time >= timeout_seconds) { + printf("⚠ 警告: 服务器响应超时(%.2f秒)\n", receive_time); + } + + if (bytes_received <= 0) { + int err = SSL_get_error(ssl, bytes_received); + fprintf(stderr, "接收数据失败,错误代码: %d\n", err); + return 0; + } + + buffer[bytes_received] = '\0'; + printf("接收到 %d 字节响应:\n", bytes_received); + printf("--- 响应内容 ---\n"); + printf("%s\n", buffer); + printf("--- 响应结束 ---\n"); + + // 检查是否收到预期的HTTP响应 + if (strstr(buffer, "HTTP/1.1 200 OK") && strstr(buffer, "Hello from TLS server!")) { + printf("✓ 收到预期的HTTP响应\n"); + } else { + printf("⚠ 响应内容与预期不符\n"); + } + + return 1; +} + +/** + * @brief 执行单次TLS测试 + * @param hostname 服务器主机名 + * @param port 服务器端口 + * @param cert_file 客户端证书文件 + * @param key_file 客户端私钥文件 + * @param ca_file CA证书文件 + * @return int 成功返回1,失败返回0 + */ +int perform_tls_test(const char* hostname, int port, const char* cert_file, + const char* key_file, const char* ca_file, int verify_peer, int tls_version, int debug_level) { + int sockfd; + SSL* ssl; + SSL_CTX* local_ctx = NULL; + int success = 0; + + // 创建TCP连接 + sockfd = create_tcp_connection(hostname, port); + if (sockfd < 0) { + return 0; + } + + // 创建本地SSL上下文(如果提供了tls_version参数) + if (tls_version > 0) { + printf("为TLS版本 %d 创建SSL上下文...\n", tls_version); + local_ctx = create_ssl_context(cert_file, key_file, ca_file, verify_peer, tls_version, debug_level); + if (!local_ctx) { + fprintf(stderr, "创建SSL上下文失败\n"); + close(sockfd); + return 0; + } + printf("SSL上下文创建成功\n"); + } + + // 创建SSL连接 + ssl = SSL_new(local_ctx ? local_ctx : ssl_ctx); + if (!ssl) { + fprintf(stderr, "创建SSL连接失败\n"); + if (local_ctx) { + SSL_CTX_free(local_ctx); + } + close(sockfd); + return 0; + } + + // 将套接字绑定到SSL连接 + SSL_set_fd(ssl, sockfd); + + // 执行TLS握手 + if (perform_tls_handshake(ssl)) { + // 发送测试数据 + if (send_test_data(ssl)) { + // 接收响应 + if (receive_response(ssl)) { + success = 1; + } + } + } + + // 安全关闭SSL连接和套接字 + if (ssl) { + // 检查SSL连接状态 + int shutdown_state = SSL_get_shutdown(ssl); + printf("SSL关闭前状态: %d\n", shutdown_state); + + if (shutdown_state == 0) { + // 连接仍然活跃,需要优雅关闭 + printf("开始优雅关闭SSL连接...\n"); + + // 设置SSL关闭模式为双向关闭 + SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + + // 尝试优雅关闭SSL连接 + int ret = SSL_shutdown(ssl); + printf("第一次SSL_shutdown返回: %d\n", ret); + + if (ret == 0) { + // 需要再次调用SSL_shutdown完成双向关闭 + printf("执行第二次SSL关闭...\n"); + ret = SSL_shutdown(ssl); + printf("第二次SSL_shutdown返回: %d\n", ret); + } + + // 等待一段时间确保关闭完成 + usleep(100000); // 等待100ms + } + + // 释放SSL对象 + SSL_free(ssl); + } + + // 关闭套接字 + if (sockfd > 0) { + // 检查套接字状态 + int error = 0; + socklen_t len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { + if (error != 0) { + printf("套接字错误: %d\n", error); + } + } + + // 设置套接字选项,避免TIME_WAIT状态 + int opt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + perror("设置SO_REUSEADDR失败"); + } + + // 设置LINGER选项,确保数据发送完成 + struct linger linger_opt; + linger_opt.l_onoff = 1; + linger_opt.l_linger = 5; // 等待5秒 + if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)) < 0) { + perror("设置SO_LINGER失败"); + } + + // 关闭套接字 + close(sockfd); + } + + if (local_ctx) { + SSL_CTX_free(local_ctx); + } + + return success; +} + +/** + * @brief 执行TLS版本循环测试 + * @param hostname 服务器主机名 + * @param port 服务器端口 + * @param cert_file 客户端证书文件 + * @param key_file 客户端私钥文件 + * @param ca_file CA证书文件 + * @param verify_peer 是否验证服务器证书 + * @param test_count 测试次数 (-1表示无限循环) + * @param interval 测试间隔 + * @return int 成功返回1,失败返回0 + */ +int perform_tls_version_test(const char* hostname, int port, const char* cert_file, + const char* key_file, const char* ca_file, int verify_peer, + int test_count, int interval, int continue_on_failure, int debug_level) { + int test_num = 0; + int success_count = 0; + int total_tests = 0; + time_t start_time, end_time; + + printf("=== TLS版本循环测试开始 ===\n"); + printf("服务器: %s:%d\n", hostname, port); + printf("测试模式: TLS 1.2 -> TLS 1.3 -> 重复\n"); + printf("测试次数: %s\n", test_count == -1 ? "无限循环" : "有限次数"); + printf("测试间隔: %d 秒\n", interval); + printf("========================\n\n"); + + start_time = time(NULL); + + while (test_count == -1 || test_num < test_count) { + test_num++; + total_tests++; + + // 测试TLS 1.2 + printf("\n--- 第 %d 次测试 - TLS 1.2 ---\n", test_num); + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 1, debug_level)) { + printf("✓ TLS 1.2 测试成功\n"); + success_count++; + } else { + printf("✗ TLS 1.2 测试失败\n"); + if (!continue_on_failure) { + printf("TLS 1.2 测试失败,退出测试循环\n"); + break; // 失败时退出循环 + } else { + printf("TLS 1.2 测试失败,继续测试\n"); + } + } + + // 等待间隔 + if (interval > 0) { + sleep(interval); + } + + // 测试TLS 1.3 + printf("\n--- 第 %d 次测试 - TLS 1.3 ---\n", test_num); + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 2, debug_level)) { + printf("✓ TLS 1.3 测试成功\n"); + success_count++; + } else { + printf("✗ TLS 1.3 测试失败\n"); + if (!continue_on_failure) { + printf("TLS 1.3 测试失败,退出测试循环\n"); + break; // 失败时退出循环 + } else { + printf("TLS 1.3 测试失败,继续测试\n"); + } + } + + // 如果不是最后一次测试,等待指定间隔 + if (test_count == -1 || test_num < test_count) { + if (interval > 0) { + printf("等待 %d 秒后进行下次测试...\n", interval); + sleep(interval); + } + } + } + + end_time = time(NULL); + + // 打印测试统计 + printf("\n=== 测试统计 ===\n"); + printf("总测试次数: %d (TLS 1.2: %d次, TLS 1.3: %d次)\n", total_tests * 2, total_tests, total_tests); + printf("成功次数: %d\n", success_count); + printf("失败次数: %d\n", total_tests * 2 - success_count); + printf("成功率: %.2f%%\n", total_tests > 0 ? (double)success_count / (total_tests * 2) * 100 : 0); + printf("总耗时: %ld 秒\n", end_time - start_time); + printf("===============\n"); + + return success_count > 0 ? 1 : 0; +} + +/** + * @brief 打印使用说明 + */ +void print_usage(const char* program_name) { + printf("用法: %s [选项]\n", program_name); + printf("选项:\n"); + printf(" -h 服务器主机名或IP地址 (默认: 127.0.0.1)\n"); + printf(" -p 服务器端口 (默认: 443)\n"); + printf(" -c 客户端证书文件 (必需)\n"); + printf(" -k 客户端私钥文件 (必需)\n"); + printf(" -a CA证书文件 (可选)\n"); + printf(" -n 测试次数 (默认: 无限循环)\n"); + printf(" -i 测试间隔秒数 (默认: 1)\n"); + printf(" -v 详细输出\n"); + printf(" -x 禁用服务器证书验证\n"); + printf(" -t TLS版本 (1=TLS1.2, 2=TLS1.3, 3=循环测试1.2和1.3)\n"); + printf(" -f 失败时继续测试(默认:失败时退出)\n"); + printf(" -d OpenSSL调试级别 (0=无, 1=基本, 2=详细, 3=完整)\n"); + printf(" --no-verify 禁用服务器证书验证\n"); + printf(" --help 显示此帮助信息\n"); + printf("\n示例:\n"); + printf(" %s -h 192.168.1.100 -p 8443 -c client.crt -k client.key\n", program_name); + printf(" %s -h example.com -p 443 -c client.crt -k client.key -a ca.crt -n 10\n", program_name); +} + +int main(int argc, char *argv[]) { + char hostname[256] = "127.0.0.1"; + int port = 443; + char cert_file[256] = ""; + char key_file[256] = ""; + char ca_file[256] = ""; + int test_count = -1; // -1表示无限循环 + int interval = 1; + int verbose = 0; + int no_verify = 0; // 是否禁用服务器证书验证 + int tls_version = 3; // 默认循环测试TLS 1.2和1.3 + int continue_on_failure = 0; // 失败时是否继续测试 + int debug_level = 0; // OpenSSL调试级别 + int opt; + int test_num = 0; + int success_count = 0; + int total_tests = 0; + time_t start_time, end_time; + + // 预处理长选项,将它们转换为短选项 + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--no-verify") == 0) { + no_verify = 1; + // 移除这个参数,避免getopt处理 + for (int j = i; j < argc - 1; j++) { + argv[j] = argv[j + 1]; + } + argc--; + i--; + } else if (strcmp(argv[i], "--help") == 0) { + print_usage(argv[0]); + return 0; + } + } + + // 解析命令行参数 + while ((opt = getopt(argc, argv, "h:p:c:k:a:n:i:vxt:fd:")) != -1) { + switch (opt) { + case 'h': + strncpy(hostname, optarg, sizeof(hostname) - 1); + break; + case 'p': + port = atoi(optarg); + break; + case 'c': + strncpy(cert_file, optarg, sizeof(cert_file) - 1); + break; + case 'k': + strncpy(key_file, optarg, sizeof(key_file) - 1); + break; + case 'a': + strncpy(ca_file, optarg, sizeof(ca_file) - 1); + break; + case 'n': + test_count = atoi(optarg); + break; + case 'i': + interval = atoi(optarg); + break; + case 'v': + verbose = 1; + break; + case 'x': + no_verify = 1; + break; + case 't': + tls_version = atoi(optarg); + if (tls_version < 1 || tls_version > 3) { + fprintf(stderr, "错误: TLS版本必须是1、2或3\n"); + print_usage(argv[0]); + return 1; + } + break; + case 'f': + continue_on_failure = 1; + break; + case 'd': + debug_level = atoi(optarg); + if (debug_level < 0 || debug_level > 3) { + fprintf(stderr, "错误: 调试级别必须是0-3\n"); + print_usage(argv[0]); + return 1; + } + break; + default: + print_usage(argv[0]); + return 1; + } + } + + // 检查必需参数 + if (strlen(cert_file) == 0 || strlen(key_file) == 0) { + fprintf(stderr, "错误: 必须指定客户端证书和私钥文件\n"); + print_usage(argv[0]); + return 1; + } + + // 初始化OpenSSL + init_openssl(debug_level); + + // 根据TLS版本选择测试模式 + if (tls_version == 3) { + // 循环测试TLS 1.2和1.3 + return perform_tls_version_test(hostname, port, cert_file, key_file, + ca_file[0] ? ca_file : NULL, !no_verify, + test_count, interval, continue_on_failure, debug_level); + } else { + // 单版本测试 + // 创建SSL上下文 + ssl_ctx = create_ssl_context(cert_file, key_file, ca_file[0] ? ca_file : NULL, !no_verify, tls_version, debug_level); + if (!ssl_ctx) { + fprintf(stderr, "创建SSL上下文失败\n"); + cleanup_openssl(); + return 1; + } + } + + printf("=== TLS客户端测试程序 ===\n"); + printf("服务器: %s:%d\n", hostname, port); + printf("客户端证书: %s\n", cert_file); + printf("客户端私钥: %s\n", key_file); + if (strlen(ca_file) > 0) { + printf("CA证书: %s\n", ca_file); + } + printf("测试次数: %s\n", test_count == -1 ? "无限循环" : "有限次数"); + if (test_count != -1) { + printf("计划测试: %d 次\n", test_count); + } + printf("测试间隔: %d 秒\n", interval); + printf("========================\n\n"); + + start_time = time(NULL); + + // 开始测试循环 + while (test_count == -1 || test_num < test_count) { + test_num++; + total_tests++; + + printf("\n--- 第 %d 次测试 ---\n", test_num); + + if (verbose) { + printf("开始时间: %s", ctime(&start_time)); + } + + // 执行TLS测试 + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, !no_verify, tls_version, debug_level)) { + printf("✓ 第 %d 次测试成功\n", test_num); + success_count++; + } else { + printf("✗ 第 %d 次测试失败\n", test_num); + if (!continue_on_failure) { + printf("测试失败,退出测试循环\n"); + break; // 失败时退出循环 + } else { + printf("测试失败,继续测试\n"); + } + } + + // 如果不是最后一次测试,等待指定间隔 + if (test_count == -1 || test_num < test_count) { + if (interval > 0) { + printf("等待 %d 秒后进行下次测试...\n", interval); + sleep(interval); + } + } + } + + end_time = time(NULL); + + // 打印测试统计 + printf("\n=== 测试统计 ===\n"); + printf("总测试次数: %d\n", total_tests); + printf("成功次数: %d\n", success_count); + printf("失败次数: %d\n", total_tests - success_count); + printf("成功率: %.2f%%\n", total_tests > 0 ? (double)success_count / total_tests * 100 : 0); + printf("总耗时: %ld 秒\n", end_time - start_time); + printf("===============\n"); + + // 清理资源 + cleanup_openssl(); + + return 0; +} diff --git a/tls_server.cpp b/tls_server.cpp new file mode 100644 index 0000000..5b0c732 --- /dev/null +++ b/tls_server.cpp @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int PORT = 7271; +const char* SERVER_CERT_FILE = "server.crt"; +const char* SERVER_KEY_FILE = "server.key"; +const char* CA_CERT_FILE = "ca.crt"; + +volatile sig_atomic_t server_running = 1; + +void signal_handler(int sig) { + std::cout << "\n收到信号 " << sig << ",正在关闭服务器..." << std::endl; + server_running = 0; +} + +void print_openssl_errors() { + BIO* bio = BIO_new_fp(stderr, BIO_NOCLOSE); + ERR_print_errors(bio); + BIO_free(bio); +} + +void init_openssl() { + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); +} + +void cleanup_openssl() { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_cleanup(); +#endif +} + +SSL_CTX* create_context() { + const SSL_METHOD* method = TLS_server_method(); + SSL_CTX* ctx = SSL_CTX_new(method); + + if (!ctx) { + std::cerr << "无法创建SSL上下文" << std::endl; + print_openssl_errors(); + exit(EXIT_FAILURE); + } + + SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); + SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION); + + return ctx; +} + +int verify_callback(int preverify_ok, X509_STORE_CTX* ctx) { + if (!preverify_ok) { + int err = X509_STORE_CTX_get_error(ctx); + if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) { + return 1; + } + } + return preverify_ok; +} + +void configure_context(SSL_CTX* ctx) { + if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT_FILE, SSL_FILETYPE_PEM) <= 0) { + std::cerr << "无法加载服务器证书" << std::endl; + print_openssl_errors(); + exit(EXIT_FAILURE); + } + + if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_FILE, SSL_FILETYPE_PEM) <= 0) { + std::cerr << "无法加载服务器私钥" << std::endl; + print_openssl_errors(); + exit(EXIT_FAILURE); + } + + if (!SSL_CTX_check_private_key(ctx)) { + std::cerr << "证书和私钥不匹配" << std::endl; + exit(EXIT_FAILURE); + } + + if (SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, nullptr) <= 0) { + std::cerr << "无法加载CA证书" << std::endl; + print_openssl_errors(); + exit(EXIT_FAILURE); + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); + SSL_CTX_set_verify_depth(ctx, 4); + + // 关键优化:简化SSL选项 + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); + SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256"); +} + +void graceful_ssl_close(SSL* ssl, int fd) { + if (!ssl || fd < 0) return; + + // 简化的关闭逻辑 + SSL_shutdown(ssl); + SSL_free(ssl); + close(fd); +} + +void handle_connection(SSL* ssl, int client_fd, const char* client_ip, uint16_t client_port) { + std::cout << "\n处理连接 " << client_ip << ":" << client_port << std::endl; + std::cout << "协议: " << SSL_get_version(ssl) << std::endl; + + // 验证客户端证书 + X509* client_cert = SSL_get_peer_certificate(ssl); + if (!client_cert) { + std::cerr << "客户端未提供证书" << std::endl; + graceful_ssl_close(ssl, client_fd); + return; + } + X509_free(client_cert); + + // 设置TCP_NODELAY + int optval = 1; + setsockopt(client_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)); + + // 设置60秒读取超时 + struct timeval timeout = {60, 0}; + setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + std::cout << "等待客户端数据..." << std::endl; + + // 读取客户端数据 + char buffer[4096]; + int bytes = SSL_read(ssl, buffer, sizeof(buffer)); + + if (bytes > 0) { + std::cout << "收到数据: " << bytes << "字节" << std::endl; + + // 发送响应 + const char* response = + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n" + "\r\n" + "Hello from TLS server!"; + SSL_write(ssl, response, strlen(response)); + std::cout << "已发送响应" << std::endl; + } else if (bytes == 0) { + std::cout << "客户端关闭连接" << std::endl; + } else { + std::cout << "客户端未发送数据(超时)" << std::endl; + } + + graceful_ssl_close(ssl, client_fd); +} + +int main() { + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + init_openssl(); + SSL_CTX* ctx = create_context(); + configure_context(ctx); + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } + + int optval = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(PORT); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(sockfd, (sockaddr*)&addr, sizeof(addr)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + + if (listen(sockfd, 10) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + std::cout << "服务器监听端口 " << PORT << std::endl; + + while (server_running) { + sockaddr_in client_addr{}; + socklen_t client_len = sizeof(client_addr); + int client_fd = accept(sockfd, (sockaddr*)&client_addr, &client_len); + + if (client_fd < 0) { + if (server_running) perror("accept"); + continue; + } + + char client_ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN); + uint16_t client_port = ntohs(client_addr.sin_port); + + SSL* ssl = SSL_new(ctx); + SSL_set_fd(ssl, client_fd); + + if (SSL_accept(ssl) <= 0) { + std::cerr << "SSL握手失败: "; + print_openssl_errors(); + SSL_free(ssl); + close(client_fd); + continue; + } + + handle_connection(ssl, client_fd, client_ip, client_port); + } + + close(sockfd); + SSL_CTX_free(ctx); + cleanup_openssl(); + return 0; +} \ No newline at end of file