AES-NI sa VPS: Paano I-check at Ibalik
Alamin kung nakikita ng VPS ang AES-NI, sukatin ang epekto ng masked CPUID sa AES-GCM throughput, at ibalik ang bits gamit ang OPENSSL_ia32cap.
Ano talaga ang naibibigay ng AES-NI sa isang VPS
Ang AES-NI sa isang VPS ay set ng anim na x86 instruction na nagsasagawa ng isang round ng AES (advanced encryption standard) sa hardware. Kung itinatago ng CPU model ng provider mo ang mga ito, nasa silicon pa rin ang mga instruction, pero hindi makita ng OpenSSL ang mga ito at bumabalik ito sa software implementation na humihingi ng humigit-kumulang sampung beses na mas maraming cycle bawat byte. Maaari mong tingnan ang feature sa isang command, sukatin ang diperensya sa dalawang command, at kadalasan ay maibalik ang fast path gamit ang isang environment variable.
Ang mga instruction ay AESENC, AESENCLAST, AESDEC, AESDECLAST, AESIMC at AESKEYGENASSIST. Inilabas ito ng Intel noong 2010 at sinundan ito ng AMD, kaya may ganitong silicon ang halos lahat ng server CPU na malamang mong rentahan. Ang kasamang instruction na PCLMULQDQ ay nagsasagawa ng carry-less multiplication, na kailangan ng GCM (Galois/counter mode) upang mabuo ang authentication tag nito. Mabilis lamang ang AES-GCM kapag available ang dalawang ito, dahil magkahiwalay na gawain ang cipher at ang tag.
Apat na lugar sa isang VPS kung saan makikita ito sa monitoring mo:
- TLS (transport layer security) termination. Ang web server na naghahatid ng AES-128-GCM o AES-256-GCM ay ginugugol ang malaking bahagi ng bulk-crypto time nito sa AES.
- Encrypted volumes. Isinasagawa ng LUKS (Linux unified key setup) at dm-crypt ang
aes-xtssa bawat read at bawat write, sa kernel at sa CPU. - AES-based VPN traffic. Umaasa rito ang OpenVPN na may
AES-256-GCMat ang IPsec na may AES-GCM. - Encrypted backups. Anumang nag-e-encrypt ng stream gamit ang AES bago ito umalis sa server ay nagbabayad ng parehong cost.
May isang karaniwang workload na hindi talaga naaapektuhan. Gumagamit ang WireGuard ng ChaCha20-Poly1305 para sa data nito at hindi gumagamit ng AES, kaya pareho ang bilis ng isang self-hosted WireGuard VPN sa host na naka-mask ang flag. Praktikal na dahilan ang diperensyang ito para isaalang-alang ang WireGuard kumpara sa OpenVPN bago pumili ng tunnel para sa murang VPS.
Paano tingnan kung may AES-NI ang iyong VPS
Kinokopya ng kernel ang CPUID feature bits sa /proc/cpuinfo, kaya isang grep lang ang makasasagot sa tanong.
grep -m1 -o '\baes\b' /proc/cpuinfo
lscpu | grep -i -o '\baes\b'Ang alinmang command na nagpi-print ng aes ay nangangahulugang ipinapakita ng CPU ang AES-NI para sa guest na ito. Kapag walang na-print, wala itong AES-NI. Binabasa ng lscpu ang parehong flags, kaya palaging magkatugma ang dalawang command. Gamitin ang alinman sa mga naka-install.
Tingnan ngayon kung aling CPU ang sinasabing ginagamit mo ng host.
grep -m1 'model name' /proc/cpuinfoAng totoong model string gaya ng Intel(R) Xeon(R) Gold 6338 CPU @ 2.00GHz o AMD EPYC 7443P 24-Core Processor ay nangangahulugang ipinapasa sa iyo ng host ang pisikal na CPU model. Ang QEMU Virtual CPU version 2.5+ o Common KVM processor ay nangangahulugang may ibang nangyayari, at ang kasong iyon ang dapat maunawaan.
Bakit nawawala ang flag kahit mayroon nito ang silicon
Ang CPUID ang instruction na ginagamit ng isang program para itanong sa CPU kung ano ang sinusuportahan nito. Sa loob ng virtual machine, palaging nagta-trap ang CPUID papunta sa hypervisor, kaya ang hypervisor ang nagpapasya kung ano ang ipapaalam sa guest. Karamihan sa mga panel ay inilalantad ang pasyang iyon bilang guest CPU model. Ang qemu64 at kvm64 ay generic baseline model, at wala sa feature set ng alinman sa mga ito ang AES-NI o SSSE3. Kaya walang nakikitang aes flag ang guest kahit kasalukuyang EPYC ang physical host. Ang VPS ay guest sa hardware ng ibang tao, kaya ang bawat feature na iniuulat nito ay pasyang ginawa sa mas mataas na layer. Kung bago sa iyo ang ganitong layering, magsimula sa kung ano ang VPS.
Sadyang pumipili ang mga host ng generic model dahil gagana lamang ang live migration sa pagitan ng mga machine na may magkakaibang processor kung hindi kailanman naipaalam sa guest ang feature na wala sa destination. Ikaw ang sumasagot sa kapalit nito. Binabasa ng iyong kernel at ng kopya mo ng OpenSSL ang naka-mask na CPUID na iyon sa pagsisimula, at pagkatapos ay pareho silang pumipili ng mabagal na code path habang tumatakbo ang process.
Ang solusyon sa pinagmulan ay isang host-side setting: -cpu host sa terminolohiya ng QEMU, isang named model na may AES-NI, o isang tahasang +aes na idinagdag sa model. Hindi mo maitatakda ang alinman dito mula sa loob ng guest. Ang pagbubukas ng support ticket o pagpili ng plan na nagpapadaan sa hypervisor ng CPU model ang pangmatagalang solusyon.
Sukatin ang agwat gamit ang openssl speed
Huwag basta maniwala sa benchmark na inilathala. Patakbuhin ang cipher na aktuwal na nino-negotiate ng sarili mong server.
openssl version
openssl speed -evp aes-128-gcmAng result row ay may label na AES-128-GCM at nagbibigay ng throughput sa anim na block size, na nasa unit na 1000 bytes bawat segundo. Basahin ang column na 8192-byte para sa bulk transfer, dahil dominado ng per-call overhead ang column na 16-byte at wala itong sinasabi tungkol sa file download.
Ngayon, patakbuhin ang parehong command nang naka-off sa software ang AES-NI at PCLMULQDQ:
OPENSSL_ia32cap="~0x200000200000000" openssl speed -evp aes-128-gcmAng value na iyon ay mula sa sariling capability vector documentation ng OpenSSL. Ang nauunang ~ ay nangangahulugang “i-clear ang mga bit na ito.” Ang bit 57 ay AES-NI at ang bit 33 ay PCLMULQDQ, kaya eksaktong ang dalawang iyon at wala nang iba ang tinutukoy ng 0x200000200000000. Kung mas mababa nang malaki ang ikalawang number kaysa sa una, gumagana ang AES-NI ng iyong machine at tapos na ang pagsusuri. Kung magkapareho ang dalawang number, nasa software path na ang OpenSSL mula pa noong una, dahil wala roon ang flag na kailangang i-clear.
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
}
]Mga representative na figure lamang ang mga iyon mula sa mga modernong x86 core na nasa humigit-kumulang 3.4 GHz; hindi iyon measurement mula sa isang partikular na host. Basahin ang mga ito bilang pangkalahatang pattern. Tumatakbo ang hardware path sa humigit-kumulang 0.7 cycles bawat byte, samantalang ang software fallback ay nasa humigit-kumulang 11.0, na katumbas ng humigit-kumulang 4,850 MB/s kumpara sa 310 MB/s sa isang core. Ang dalawang command sa itaas lamang ang nagbibigay ng value na naglalarawan sa iyong server. Nalalapat din ang parehong paraan sa iba pang bahagi ng machine, kaya ipares ito sa paulit-ulit na paraan ng pag-benchmark ng isang VPS bago bumuo ng konklusyon tungkol sa isang plan.
Ibalik ang bits gamit ang OPENSSL_ia32cap
Narito ang bahaging kadalasang nakakagulat. Unprivileged ang AES-NI instructions, at hindi tina-trap ng hypervisor ang mga ito. CPUID lang ang tina-trap. Kaya maaaring sabihin ng host sa guest mo na wala ang AES-NI habang patuloy na native na tumatakbo ang AESENC sa buong bilis. Nilalaktawan ng software ang fast path dahil nagtanong ito sa CPUID at nakatanggap ng maling sagot. Hindi kailanman tumigil sa paggana ang instruction mismo.
Hinahayaan ka ng OpenSSL na sumagot sa ngalan ng CPU. Ang plain hexadecimal value sa OPENSSL_ia32cap ay nag-o-overwrite sa capability vector sa halip na mag-mask nito.
OPENSSL_ia32cap="0x0200020207000000" openssl speed -evp aes-128-gcmKung ilang beses na mas mabilis ang run na iyon kaysa sa plain run, may AES-NI ang silicon at itinatago ito ng host. Diagnosis muna ito. Para sa OpenSSL, nagsisilbi rin itong fix.
Paano binubuo ang hex value na iyon
Pinagsasama ng unang logical vector ang CPUID leaf 1 EDX sa low 32 bits at ang leaf 1 ECX sa high 32 bits. Sa low half, ang bit 24 ay FXSR, ang bit 25 ay SSE, at ang bit 26 ay SSE2, kaya nabubuo ang 0x07000000. Sa upper half, ang bit 33 ay PCLMULQDQ, ang bit 41 ay SSSE3, at ang bit 57 ay AES-NI, kaya nabubuo ang 0x02000202. Kapag pinagsama, iyon ay 0x0200020207000000. Kasama sa listahan ang SSSE3 dahil ginagamit ng GHASH na nakabatay sa PCLMULQDQ ng OpenSSL ang pshufb upang mag-swap ng bytes, at itinatago ng generic guest CPU model ang SSSE3 kasabay ng AES-NI.
May dalawang babala, at maaari mong sadyang ma-trigger ang pareho.
Kapag ang unang vector lang ang itinakda, magiging zero ang mga susunod na vector. Dahil dito, mao-off ang AVX2 at AVX-512 code paths. Sinasadya ito rito. Huwag subukang i-force ang AVX bits sa masked guest, dahil kailangang i-enable ng operating system ang extended state ng mga AVX register sa XCR0, at tumanggi rito ang kernel batay sa parehong masked CPUID. Magtataas ang isang VEX-encoded instruction ng undefined-opcode fault, at mamamatay ang process.
Kapag ni-force ang AES-NI sa core na tunay na walang nito, agad mamamatay ang process:
Illegal instruction (core dumped)Iyon ay AESENC na nagtataas ng undefined-opcode fault dahil walang ganoong instruction na maaaring i-execute sa core na iyon. Maaari ring i-disable ng ilang server firmware ang AES-NI sa hardware hanggang sa susunod na reset, at pareho ang magiging sintomas. Sa alinmang kaso, ibang host ang solusyon, hindi ibang environment variable.
Para manatili ang override sa isang long-running service, gumamit ng systemd drop-in.
sudo systemctl edit nginx[Service]
Environment="OPENSSL_ia32cap=0x0200020207000000"sudo systemctl daemon-reload
sudo systemctl restart nginx
sudo systemctl show nginx -p EnvironmentDapat i-print pabalik sa iyo ng huling command ang variable. Unawain ang pinapasok mo: kung ma-migrate ang server na iyon sa host na tunay na walang AES-NI, mamamatay ang nginx dahil sa illegal instruction sa unang TLS connection nito. Isama ito sa runbook, o huwag na lang ilagay ang override sa production at gamitin lamang ito upang patunayan ang punto kapag nagbukas ka ng ticket.
Ano ang hindi inaayos ng override
OPENSSL_ia32cap lamang ang naaabot ng OpenSSL, at wala nang iba. Ang bawat iba pang software ay may sarili nitong feature detection at hindi kailanman nagbabasa ng variable na iyon.
Ang kernel ang mahalagang kaso. Ginagamit ng dm-crypt at LUKS ang kernel crypto API, at tumatangging mag-load ang module na aesni_intel kapag wala ang CPU feature bit:
modprobe: ERROR: could not insert 'aesni_intel': No such deviceWalang user-space variable para rito. Isang beses lang binabasa ng kernel ang CPUID sa boot, at mananatili ang desisyong iyon hanggang mag-reboot ka sa ibang host. Kaya mananatili ang encrypted volume mo sa software cipher, anuman ang ginagawa ng OpenSSL. Sukatin kung ano talaga ang ginagamit mo:
sudo cryptsetup benchmark -c aes-xts -s 256Ang row na aes-xts 256b ay umaabot sa libo-libong MiB/s kapag may hardware AES, at nasa mababang daan-daang MiB/s kapag wala nito. Hindi rin maaabot ang language runtime na may sarili nitong detection, kabilang ang Go at Java. Direktang sinusuri ng crypto/aes ng Go ang CPUID at tahimik na gumagamit ng constant-time software implementation nito kapag clear ang bit. Kung Go binary ang service na nagte-terminate ng TLS mo, walang binabago rito ang OpenSSL variable.
Kung hindi available ang AES-NI, mas piliin ang ChaCha20
Dinisenyo ang ChaCha20-Poly1305 upang maging mabilis sa plain software. Sa core na walang magagamit na AES-NI, karaniwan itong mas mabilis nang malaki kaysa AES-GCM. Kaya sa ganitong host, mas angkop na huwag nang unahin ang AES.
Para sa nginx 1.19.4 at mas bago, na bina-build gamit ang OpenSSL 1.1.1 o mas bago:
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;Sinasaklaw ng ssl_ciphers ang TLS 1.2. Sinasaklaw ng ssl_conf_command Ciphersuites ang TLS 1.3. Para rito, walang dedicated directive ang nginx at ipinapasa nito ang string nang direkta sa OpenSSL nang hindi ito vine-verify. Dahil dito, tahimik na tinatanggap ang typo. I-reload at kumpirmahin kung ano ang ino-offer sa client:
sudo nginx -t && sudo systemctl reload nginx
openssl s_client -connect example.com:443 -tls1_3 </dev/null 2>/dev/null | grep -i cipherAng tamang resulta ay dapat magbanggit ng TLS_CHACHA20_POLY1305_SHA256. Bago mong i-commit ang pagbabago, patakbuhin ang openssl speed -evp chacha20-poly1305 kasabay ng AES run sa parehong box. Hayaan ang dalawang numero ang magpasya.
Iba ang mga extension sa ARM hosts
x86 lamang ang AES-NI. Gumagamit ang ARM VPS ng ARMv8 cryptographic extensions, isang hiwalay na instruction set na gumagawa ng parehong gawain. Sa aarch64, nasa ilalim ng Features ang mga flag sa halip na flags:
grep -m1 Features /proc/cpuinfoHanapin ang aes at pmull. Ang pmull ang katumbas sa ARM ng PCLMULQDQ, at kailangan ito ng GCM sa parehong dahilan. Sa ARM, ang override variable ng OpenSSL ay OPENSSL_armcap. May sarili itong bit layout na tinutukoy sa crypto/arm_arch.h sa source ng OpenSSL, kaya walang kahulugan doon ang x86 hex value sa gabay na ito. Sa aktuwal na paggamit, karaniwang inilalantad ng ARM server cores na ibinebenta bilang VPS hosts ang mga extension na ito. Kaya higit na problema ng x86 ang masked-feature issue.
Mga failure mode at mga string na makikita mo
Walang aes sa /proc/cpuinfo, at mas mabilis ang forced run. Mina-mask ng host ang CPUID. Tiyaking generic ang model name, pagkatapos ay tanungin ang provider kung anong guest CPU model ang ipinapakita ng hypervisor nila.
Walang aes sa /proc/cpuinfo, at ipinapakita ng forced run ang Illegal instruction. Talagang wala ang mga instruction, o hindi pinagana ang mga ito ng firmware. Ilipat ang workload sa ibang host.
Nariyan ang aes pero mababa pa rin ang throughput. Tiyaking binabasa mo ang column na 8192-byte, at walang ibang gumagamit sa core. Sa shared plan, eksaktong katulad ng nawawalang CPU feature ang epekto ng maingay na katabing tenant hanggang patakbuhin mo ang test nang dalawang beses sa magkaibang oras ng araw.
Pareho ang resulta ng masked run at normal run. Nasa software path na ang OpenSSL. Iyan ang finding, hindi pagkakamali sa test.
Binabago ng nested virtualisation ang resulta sa isang level sa loob. Ang guest sa loob ng guest ay tumatanggap ng CPUID na piniling ipasa ng middle layer, at madaling mawala roon ang AES-NI nang hindi napapansin. Kung nagpapatakbo ka ng nested virtual machines sa isang VPS, tingnan din ang flag sa loob ng inner guest, pati sa machine na ni-rent mo.
FAQ
Bakit walang aes flag ang aking VPS sa /proc/cpuinfo?
Dahil generic guest CPU model ang ipinapakita ng hypervisor. Hindi kasama ng qemu64 at kvm64 ang AES-NI sa kanilang feature sets, kaya iniulat ng CPUID na wala ito anuman ang aktuwal na physical processor. Ginagawa ito ng mga host upang mailipat ang tumatakbong guest sa pagitan ng mga machine na magkakaiba ang CPU. Patakbuhin ang grep -m1 'model name' /proc/cpuinfo: ang string na gaya ng QEMU Virtual CPU version 2.5+ o Common KVM processor ang palatandaan, samantalang ang tunay na Xeon o EPYC model string ay nangangahulugang ipinapasa ang CPU model at talagang wala ang flag sa silicon.
Talaga bang ina-enable ng OPENSSL_ia32cap ang AES-NI, o nagpapanggap lamang ito?
Ina-enable nito ang mga aktuwal na instruction. Unprivileged ang AES-NI instructions at hindi kailanman hina-handle ng hypervisor sa pamamagitan ng trap, kaya native na ine-execute ng AESENC ang mga ito anuman ang iniulat ng CPUID. Ang CPUID instruction lamang ang hina-harang. Kapag itinakda ang OPENSSL_ia32cap sa plain hexadecimal value, pinapalitan nito ang sagot na nakuha ng OpenSSL mula sa CPUID. Dahil dito, pinipili ng OpenSSL ang hardware code path nito at ine-execute ito ng hardware sa buong bilis. Kung tunay na wala ang mga instruction sa silicon, mamamatay ang process na may Illegal instruction (core dumped) sa unang AES operation.
Bibilis ba ng override ang aking LUKS encrypted volume?
Hindi. Binabasa ang OPENSSL_ia32cap ng OpenSSL lamang. Hindi ito ginagamit ng iba. Gumagamit ang LUKS at dm-crypt ng kernel crypto API, kung saan nabibigo ang pag-load ng aesni_intel module na may modprobe: ERROR: could not insert 'aesni_intel': No such device kapag clear ang feature bit. Binabasa ng kernel ang CPUID sa boot, at walang user-space variable na makapagbabago nito. Sukatin ang aktuwal na resulta gamit ang sudo cryptsetup benchmark -c aes-xts -s 256 at ihambing ang aes-xts 256b row sa isang host na nag-uulat ng flag.
Pinapabagal ba ng nawawalang AES-NI flag ang WireGuard?
Hindi. Gumagamit ang WireGuard ng ChaCha20-Poly1305 para sa lahat ng data at hindi kailanman gumagamit ng AES instructions, kaya pareho ang throughput nito sa masked at unmasked host. Bumababa naman ang throughput ng OpenVPN at IPsec na naka-configure sa AES-GCM kapag walang AES-NI ang host. Dahil dito, maaaring magkaiba nang malaki ang asal ng dalawang tunnel sa iisang VPS. Mahalagang malaman ito bago sisihin ang network.
Paano ko susuriin kung may AES-NI sa isang ARM VPS?
Walang AES-NI ang ARM cores. Mayroon silang ARMv8 cryptographic extensions, na gumagawa ng parehong trabaho gamit ang ibang instructions. Patakbuhin ang grep -m1 Features /proc/cpuinfo at hanapin ang aes at pmull, dahil inililista ng aarch64 ang mga ito sa ilalim ng Features sa halip na flags. Walang kahulugan sa ARM ang x86 OPENSSL_ia32cap value. Ang katumbas na variable ng OpenSSL doon ay OPENSSL_armcap, at tinutukoy ang bit layout nito sa crypto/arm_arch.h sa source ng OpenSSL.