Cara Semak dan Aktifkan AES-NI pada VPS
Ketahui cara menyemak sokongan AES-NI pada VPS anda. Ketahui kesan prestasi CPUID yang disembunyikan dan cara memaksa pengaktifan semula menggunakan pemboleh ubah OPENSSL_ia32cap.
Apakah manfaat sebenar AES-NI pada VPS
AES-NI pada VPS ialah set enam arahan x86 yang melaksanakan satu pusingan AES (advanced encryption standard) dalam perkakasan. Jika model CPU pembekal anda menyembunyikannya, silikon di bawahnya masih memilikinya, namun OpenSSL tidak dapat mengesannya dan kembali kepada pelaksanaan perisian yang memakan kira-kira sepuluh kali ganda kitaran per bait. Anda boleh menyemak ciri ini dengan satu arahan, mengukur jurang perbezaan dengan dua arahan, dan sering kali memaksa laluan pantas kembali aktif dengan satu pemboleh ubah persekitaran.
Arahan tersebut ialah AESENC, AESENCLAST, AESDEC, AESDECLAST, AESIMC dan AESKEYGENASSIST. Intel melancarkannya pada tahun 2010 dan AMD mengikutinya, jadi mana-mana CPU pelayan yang anda sewa kemungkinan besar mempunyai silikon tersebut. Arahan pendamping, PCLMULQDQ, melakukan pendaraban carry-less, iaitu apa yang diperlukan oleh GCM (Galois/counter mode) untuk membina tag pengesahannya. AES-GCM hanya pantas apabila kedua-duanya tersedia, kerana cipher dan tag adalah tugasan yang berasingan.
Empat tempat pada VPS di mana perkara ini kelihatan dalam pemantauan anda:
- Penamatan TLS (transport layer security). Pelayan web yang mengendalikan AES-128-GCM atau AES-256-GCM menghabiskan kebanyakan masa bulk-crypto di dalam AES.
- Volume yang disulitkan. LUKS (Linux unified key setup) dan dm-crypt menjalankan
aes-xtspada setiap bacaan dan setiap penulisan, di dalam kernel, pada CPU. - Trafik VPN berasaskan AES. OpenVPN dengan
AES-256-GCMdan IPsec dengan AES-GCM kedua-duanya bergantung kepadanya. - Sandaran yang disulitkan. Apa-apa sahaja yang menyulitkan aliran data dengan AES sebelum ia meninggalkan pelayan akan menanggung kos yang sama.
Satu beban kerja biasa tidak terjejas sama sekali. WireGuard menggunakan ChaCha20-Poly1305 untuk datanya dan tidak pernah menyentuh AES, jadi VPN WireGuard yang dihoskan sendiri berjalan pada kelajuan yang sama pada hos dengan flag yang disembunyikan. Perbezaan itu adalah sebab praktikal untuk menimbang WireGuard berbanding OpenVPN sebelum anda memilih tunnel untuk VPS yang murah.
Cara menyemak sama ada VPS anda mempunyai AES-NI
Kernel menyalin bit ciri CPUID ke dalam /proc/cpuinfo, jadi satu arahan grep sudah memadai untuk menjawab soalan ini.
grep -m1 -o '\baes\b' /proc/cpuinfo
lscpu | grep -i -o '\baes\b'Mana-mana arahan yang memaparkan aes bermaksud CPU mengiklankan AES-NI kepada tetamu ini. Jika tiada apa-apa yang dipaparkan, bermakna ia tidak menyokongnya. lscpu membaca flag yang sama, jadi kedua-duanya sentiasa memberikan hasil yang selaras. Gunakan mana-mana yang tersedia.
Sekarang, lihat model CPU yang didakwa oleh hos sedang digunakan oleh anda.
grep -m1 'model name' /proc/cpuinfoRentetan model sebenar seperti Intel(R) Xeon(R) Gold 6338 CPU @ 2.00GHz atau AMD EPYC 7443P 24-Core Processor bermaksud hos melalukan model CPU fizikal terus kepada anda. QEMU Virtual CPU version 2.5+ atau Common KVM processor bermaksud sesuatu yang lain sedang berlaku, dan kes tersebut adalah perkara yang perlu difahami.
Mengapa flag tiada sedangkan silikon menyokongnya
CPUID ialah arahan yang digunakan oleh program untuk bertanya kepada CPU tentang ciri yang disokongnya. Di dalam mesin maya, CPUID sentiasa memerangkap (trap) ke hypervisor, jadi hypervisor menentukan apa yang diberitahu kepada tetamu. Kebanyakan panel mendedahkan keputusan itu sebagai model CPU tetamu. qemu64 dan kvm64 adalah model asas generik, dan kedua-duanya tidak menyertakan AES-NI atau SSSE3 dalam set ciri mereka, jadi tetamu tidak melihat flag aes walaupun hos fizikal adalah EPYC terkini. VPS ialah tetamu pada perkakasan orang lain, jadi setiap ciri yang dilaporkannya adalah keputusan yang dibuat satu tahap di atas. Jika pelapisan ini baharu bagi anda, mulakan dengan apa itu VPS.
Hos memilih model generik secara sengaja, kerana migrasi langsung (live migration) antara mesin dengan pemproses berbeza hanya berfungsi jika tetamu tidak pernah diberitahu tentang ciri yang tiada pada destinasi. Kosnya ditanggung oleh anda. Kernel anda dan salinan OpenSSL anda kedua-duanya membaca CPUID yang bertopeng itu sekali semasa permulaan, dan kedua-duanya kemudian memilih laluan kod yang perlahan sepanjang hayat proses tersebut.
Penyelesaian di sumbernya ialah tetapan di pihak hos: -cpu host dalam istilah QEMU, model bernama yang menyertakan AES-NI, atau +aes eksplisit yang ditambah pada model tersebut. Anda tidak boleh menetapkan semua itu dari dalam tetamu. Membuka tiket sokongan, atau memilih pelan yang hypervisor-nya membenarkan model CPU dilalui (pass-through), adalah jawapan yang berkekalan.
Mengukur jurang dengan openssl speed
Jangan terus mempercayai penanda aras (benchmark) yang diterbitkan. Jalankan cipher yang sebenarnya dirundingkan oleh pelayan anda sendiri.
openssl version
openssl speed -evp aes-128-gcmBaris hasil dilabelkan AES-128-GCM dan memberikan daya pemprosesan (throughput) pada enam saiz blok, dalam unit 1000 bait sesaat. Baca lajur 8192-bait untuk pemindahan pukal, kerana lajur 16-bait didominasi oleh overhead setiap panggilan dan tidak memberikan maklumat tentang muat turun fail.
Sekarang, jalankan arahan yang sama dengan AES-NI dan PCLMULQDQ dimatikan dalam perisian:
OPENSSL_ia32cap="~0x200000200000000" openssl speed -evp aes-128-gcmNilai tersebut datang daripada dokumentasi vektor keupayaan OpenSSL sendiri. ~ di hadapan bermaksud "kosongkan bit ini". Bit 57 ialah AES-NI dan bit 33 ialah PCLMULQDQ, jadi 0x200000200000000 menamakan tepat dua bit tersebut dan tiada yang lain. Nombor kedua yang jauh lebih rendah daripada yang pertama bermaksud kotak anda mempunyai AES-NI yang berfungsi dan anda telah selesai. Dua nombor yang sepadan bermaksud OpenSSL sudah berada pada laluan perisian, kerana flag tersebut tidak pernah ada untuk dikosongkan.
The data behind this chart
[
{
"label": "AES-NI and PCLMULQDQ",
"mb_per_sec": "4,850",
"cycles_per_byte": 0.7
},
{
"label": "Software fallback",
"mb_per_sec": 310,
"cycles_per_byte": 11.0
}
]Itu adalah angka yang diterbitkan sebagai wakilan untuk teras x86 moden sekitar 3.4 GHz, bukan ukuran yang diambil daripada mana-mana hos tunggal. Baca angka tersebut sebagai satu bentuk corak. Laluan perkakasan berjalan pada kira-kira 0.7 kitaran per bait dan sandaran perisian pada kira-kira 11.0, yang menghasilkan kira-kira 4,850 MB/s berbanding 310 MB/s pada satu teras. Dua arahan anda di atas menghasilkan satu-satunya nombor yang menerangkan pelayan anda. Disiplin yang sama terpakai pada bahagian lain mesin, jadi gandingkan ini dengan cara boleh ulang untuk menanda aras VPS sebelum anda membuat kesimpulan tentang sesuatu pelan.
Paksa bit kembali aktif dengan OPENSSL_ia32cap
Bahagian ini sering mengejutkan ramai orang. Arahan AES-NI tidak mempunyai keistimewaan (unprivileged), dan hypervisor tidak memerangkapnya. Hanya CPUID yang diperangkap. Jadi, hos boleh memberitahu guest anda bahawa AES-NI tiada, sedangkan AESENC terus dilaksanakan secara natif pada kelajuan penuh. Perisian melangkau laluan pantas kerana ia bertanya kepada CPUID dan mendapat jawapan yang salah. Arahan itu sendiri tidak pernah berhenti berfungsi.
OpenSSL membolehkan anda menjawab bagi pihak CPU. Nilai perenambelasan (hexadecimal) biasa dalam OPENSSL_ia32cap akan menulis ganti vektor keupayaan (capability vector) dan bukannya menutupnya (masking).
OPENSSL_ia32cap="0x0200020207000000" openssl speed -evp aes-128-gcmJika larian tersebut beberapa kali lebih pantas daripada larian biasa, silikon tersebut mempunyai AES-NI dan hos anda menyembunyikannya. Itu adalah diagnosis awal. Bagi OpenSSL, ia juga kebetulan menjadi penyelesaiannya.
Cara nilai hex tersebut dibina
Vektor logik pertama memuatkan CPUID leaf 1 EDX ke dalam 32 bit rendah dan leaf 1 ECX ke dalam 32 bit tinggi. Pada bahagian bawah, bit 24 ialah FXSR, bit 25 ialah SSE dan bit 26 ialah SSE2, memberikan 0x07000000. Pada bahagian atas, bit 33 ialah PCLMULQDQ, bit 41 ialah SSSE3 dan bit 57 ialah AES-NI, memberikan 0x02000202. Apabila digabungkan, ia menjadi 0x0200020207000000. SSSE3 berada dalam senarai kerana GHASH berasaskan PCLMULQDQ dalam OpenSSL menggunakan pshufb untuk menukar bait, dan model CPU guest generik menyembunyikan SSSE3 bersama-sama AES-NI.
Dua amaran dikenakan, dan anda boleh mencetuskan kedua-duanya dengan sengaja.
Menetapkan hanya vektor pertama akan membiarkan vektor seterusnya pada sifar, yang mematikan laluan kod AVX2 dan AVX-512. Itu adalah disengajakan di sini. Jangan cuba memaksa bit AVX pada guest yang bertopeng (masked), kerana daftar AVX memerlukan sistem pengendalian untuk mendayakan keadaan lanjutan (extended state) dalam XCR0, dan kernel anda menolak untuk melakukannya berdasarkan CPUID bertopeng yang sama. Arahan berkod VEX kemudiannya akan menimbulkan ralat undefined-opcode dan proses tersebut akan mati.
Memaksa AES-NI pada teras (core) yang benar-benar tidak memilikinya akan mematikan proses serta-merta:
Illegal instruction (core dumped)Itu adalah AESENC yang menimbulkan ralat undefined-opcode, kerana pada teras tersebut tiada arahan sedemikian untuk dilaksanakan. Sesetengah perisian tegar pelayan juga boleh melumpuhkan AES-NI dalam perkakasan sehingga tetapan semula (reset) seterusnya, dan simptomnya adalah sama. Walau apa pun, jawapannya ialah hos yang berbeza, bukan pemboleh ubah persekitaran (environment variable) yang berbeza.
Untuk mengekalkan penggantian (override) bagi servis yang berjalan lama, gunakan drop-in systemd.
sudo systemctl edit nginx[Service]
Environment="OPENSSL_ia32cap=0x0200020207000000"sudo systemctl daemon-reload
sudo systemctl restart nginx
sudo systemctl show nginx -p EnvironmentArahan terakhir sepatutnya memaparkan semula pemboleh ubah tersebut kepada anda. Fahami apa yang anda lakukan: jika pelayan tersebut dipindahkan ke hos yang CPU-nya benar-benar tidak mempunyai AES-NI, nginx akan mati dengan ralat illegal instruction pada sambungan TLS pertamanya. Masukkan perkara ini ke dalam runbook anda, atau jangan gunakan penggantian tersebut dalam pengeluaran (production) sama sekali dan gunakannya hanya untuk membuktikan perkara tersebut apabila anda membuka tiket sokongan.
Perkara yang tidak diselesaikan oleh override
OPENSSL_ia32cap hanya mencapai OpenSSL dan tiada yang lain. Setiap perisian lain menjalankan pengesanan ciri tersendiri dan tidak pernah membaca pemboleh ubah tersebut.
Kernel merupakan kes yang penting. dm-crypt dan LUKS menggunakan API kripto kernel, dan modul aesni_intel enggan dimuatkan apabila bit ciri CPU tiada:
modprobe: ERROR: could not insert 'aesni_intel': No such deviceTiada pemboleh ubah ruang pengguna untuk perkara ini. Kernel membaca CPUID sekali semasa but dan keputusan itu kekal sehingga anda but semula pada hos yang berbeza, jadi volum terenkripsi anda kekal menggunakan cipher perisian tidak kira apa yang dilakukan oleh OpenSSL. Ukur apa yang anda sebenarnya perolehi:
sudo cryptsetup benchmark -c aes-xts -s 256Baris aes-xts 256b mencecah ribuan MiB/s dengan AES perkakasan dan hanya ratusan rendah tanpanya. Runtime bahasa yang mempunyai pengesanan tersendiri, termasuk Go dan Java, juga tidak terjejas. crypto/aes dalam Go menyemak CPUID secara terus dan secara senyap menggunakan implementasi perisian masa malar (constant-time) apabila bit tersebut tidak jelas. Jika servis yang menamatkan TLS anda ialah binari Go, pemboleh ubah OpenSSL tidak mengubah apa-apa untuknya.
Jika anda tidak mempunyai AES-NI, utamakan ChaCha20
ChaCha20-Poly1305 direka untuk menjadi pantas dalam perisian biasa. Pada teras tanpa AES-NI yang boleh digunakan, ia biasanya mengatasi AES-GCM dengan margin yang besar, jadi langkah yang wajar pada hos sedemikian adalah untuk berhenti mengutamakan AES.
Bagi nginx 1.19.4 dan versi lebih baharu, yang dibina menggunakan OpenSSL 1.1.1 atau lebih baharu:
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384;ssl_ciphers meliputi TLS 1.2. ssl_conf_command Ciphersuites meliputi TLS 1.3, di mana nginx tidak mempunyai arahan khusus dan menghantar rentetan terus kepada OpenSSL tanpa menyemaknya, jadi kesilapan menaip di situ akan diterima tanpa amaran. Muat semula dan sahkan apa yang ditawarkan kepada klien:
sudo nginx -t && sudo systemctl reload nginx
openssl s_client -connect example.com:443 -tls1_3 </dev/null 2>/dev/null | grep -i cipherHasil yang sihat akan menamakan TLS_CHACHA20_POLY1305_SHA256. Sebelum anda melakukan perubahan tersebut, jalankan openssl speed -evp chacha20-poly1305 bersebelahan dengan ujian AES pada mesin yang sama dan biarkan kedua-dua angka tersebut menentukan keputusan anda.
Hos ARM menggunakan sambungan yang berbeza
AES-NI hanya untuk x86. VPS ARM menggunakan sambungan kriptografi ARMv8, iaitu set arahan berasingan yang melaksanakan fungsi yang sama. Pada aarch64, flag tersebut berada di bawah Features dan bukannya flags:
grep -m1 Features /proc/cpuinfoCari aes dan pmull. pmull ialah rakan sejawat ARM bagi PCLMULQDQ, dan GCM memerlukannya atas sebab yang sama. Pemboleh ubah override OpenSSL pada ARM ialah OPENSSL_armcap, dengan susun atur bitnya sendiri yang ditakrifkan dalam crypto/arm_arch.h dalam sumber OpenSSL, jadi nilai heksadesimal x86 dalam panduan ini tidak mempunyai makna di sana. Secara praktikalnya, teras pelayan ARM yang dijual sebagai hos VPS mendedahkan sambungan ini, jadi masalah masked-feature kebanyakannya merupakan isu pada x86.
Mod kegagalan, berserta rentetan yang akan anda lihat
Tiada aes dalam /proc/cpuinfo, dan larian paksa (forced run) adalah jauh lebih pantas. Hos sedang melakukan masking pada CPUID. Sahkan bahawa nama model adalah generik, kemudian tanya pembekal anda model CPU tetamu (guest) yang dibentangkan oleh hypervisor mereka.
Tiada aes dalam /proc/cpuinfo, dan larian paksa mencetak Illegal instruction. Set arahan tersebut benar-benar tiada, atau firmware telah menyahdayakannya. Pindahkan beban kerja ke hos yang berbeza.
aes hadir tetapi throughput masih rendah. Pastikan anda membaca lajur 8192-byte, dan tiada proses lain yang menggunakan teras (core) tersebut. Pada pelan kongsi, jiran yang bising (noisy neighbour) kelihatan sama seperti ciri CPU yang hilang sehingga anda menjalankan ujian tersebut dua kali pada waktu berbeza dalam sehari.
Larian bertopeng (masked run) dan larian biasa memberikan nombor yang sama. OpenSSL sudah berada pada laluan perisian. Hasil tersebut adalah penemuan, bukan kesilapan dalam ujian.
Virtualisasi bersarang (nested virtualisation) mengubah jawapan satu tahap ke bawah. Tetamu di dalam tetamu mendapat apa sahaja CPUID yang dipilih oleh lapisan tengah untuk dilalui, dan AES-NI mudah hilang di situ tanpa disedari. Jika anda menjalankan mesin maya bersarang pada VPS, semak flag di dalam tetamu dalaman serta pada mesin yang anda sewa.
FAQ
Mengapa VPS saya tidak mempunyai flag aes dalam /proc/cpuinfo?
Ini kerana hypervisor membentangkan model CPU tetamu yang generik. qemu64 dan kvm64 tidak menyertakan AES-NI dalam set ciri mereka, jadi CPUID melaporkannya sebagai tiada tidak kira apa pun pemproses fizikalnya. Hos melakukan ini supaya tetamu yang sedang berjalan boleh dipindahkan antara mesin dengan CPU yang berbeza. Jalankan grep -m1 'model name' /proc/cpuinfo: rentetan seperti QEMU Virtual CPU version 2.5+ atau Common KVM processor adalah petunjuknya, manakala rentetan model Xeon atau EPYC yang sebenar bermakna model CPU dilalui terus (passthrough) dan flag tersebut memang tiada pada silikon.
Adakah OPENSSL_ia32cap benar-benar mendayakan AES-NI, atau ia hanya berpura-pura?
Ia mendayakan arahan sebenar. Arahan AES-NI tidak mempunyai keistimewaan dan hypervisor tidak pernah memerangkapnya, jadi AESENC dilaksanakan secara natif tidak kira apa yang dilaporkan oleh CPUID. Hanya arahan CPUID yang dipintas. Menetapkan OPENSSL_ia32cap kepada nilai heksadesimal biasa menggantikan jawapan yang diperoleh OpenSSL daripada CPUID, jadi OpenSSL memilih laluan kod perkakasan dan perkakasan kemudian menjalankannya pada kelajuan penuh. Jika silikon benar-benar tidak mempunyai arahan tersebut, proses akan terhenti dengan Illegal instruction (core dumped) pada operasi AES yang pertama.
Adakah penggantian (override) ini akan mempercepatkan volum LUKS saya yang disulitkan?
Tidak. OPENSSL_ia32cap dibaca oleh OpenSSL dan tiada yang lain. LUKS dan dm-crypt menggunakan API kripto kernel, di mana modul aesni_intel gagal dimuatkan dengan modprobe: ERROR: could not insert 'aesni_intel': No such device apabila bit ciri tidak jelas. Kernel membaca CPUID semasa but dan tiada pemboleh ubah ruang pengguna yang mengubahnya. Ukur angka sebenar dengan sudo cryptsetup benchmark -c aes-xts -s 256 dan bandingkan baris aes-xts 256b dengan hos yang melaporkan flag tersebut.
Adakah flag AES-NI yang hilang melambatkan WireGuard?
Tidak. WireGuard menggunakan ChaCha20-Poly1305 untuk semua data dan tidak pernah menggunakan arahan AES, jadi throughput-nya adalah sama pada hos yang bertopeng dan yang tidak bertopeng. OpenVPN dan IPsec yang dikonfigurasikan dengan AES-GCM memang kehilangan throughput pada hos tanpa AES-NI. Oleh itu, dua terowong pada VPS yang sama boleh berkelakuan sangat berbeza, yang perlu diketahui sebelum anda menyalahkan rangkaian.
Bagaimanakah cara saya menyemak AES-NI pada VPS ARM?
Teras ARM tidak mempunyai AES-NI. Ia mempunyai sambungan kriptografi ARMv8, yang melakukan tugas yang sama dengan arahan yang berbeza. Jalankan grep -m1 Features /proc/cpuinfo dan cari aes dan pmull, kerana aarch64 menyenaraikannya di bawah Features dan bukannya flags. Nilai OPENSSL_ia32cap x86 tidak mempunyai makna pada ARM. Pemboleh ubah setara OpenSSL di sana ialah OPENSSL_armcap, dan susun atur bitnya ditakrifkan dalam crypto/arm_arch.h dalam sumber OpenSSL.