Under the Cloud #4: Network Encryption

จริงๆ ไม่ได้กะจะมีต่อภาค 4 แต่เห็น Thread นี้ แล้วเลยอยากจะแชร์กัน เพราะผมเองก็เพิ่งรู้เหมือนกัน

คำถามวันนี้ถามว่า Network บน Cloud Secure แค่ไหน?

ทั้ง Google Cloud และ AWS ต่างมีระบบ network “Virtual Private” Cloud (VPC) ซึ่งทำให้เราเหมือนมี VLAN ส่วนตัวที่มีเฉพาะเครื่องเราคนเดียว ไม่เห็นเครื่องลูกค้าอื่น (ถ้าแต่ก่อนผมจะแซะ DigitalOcean แต่ได้ยินว่าเดี๋ยวนี้ก็มี VPC แล้วเหมือนกัน) คำถามคือแล้ว VPC มัน Secure แค่ไหน?

Going Physical

สำหรับคนที่ใช้ AWS ในสิงคโปร์น่าจะทราบดีว่า AWS จะมี 3 availability zone ด้วยกันคือ ap-southeast-1a, b และ c แล้วมันจัดโซนอย่างไร? มันจะอยู่ตึกเดียวกันหรือเปล่า?

คนที่ให้คำตอบนี้ได้ดีที่สุดคือ WikiLeaks ซึ่งผมก็ไม่รู้ว่าเค้า Leak มาทำไม

Northern Virginia (Map Data (C) OpenStreetMap Contributors)

ในสิงคโปร์อาจจะไม่เห็นชัดเท่าไร แต่ฝั่ง US จะเห็นค่อนข้างชัดว่า Region หนึ่งก็ไม่ใช่ศูนย์ข้อมูลเดียวแต่เป็นหลายๆ ตึกที่เชื่อมต่อกันด้วยไฟเบอร์ความเร็วสูง

สำหรับของ Google Cloud นั้นหน้าแนะนำ Data Center ของ Google ก็บอกเพียงแต่ว่า Google มีศูนย์ข้อมูลเพียงแห่งเดียวที่ Jurong West

ซึ่งต่อมา Google ก็บอกว่าได้ขยายศูนย์ข้อมูลเป็น 2 ตึกติดกับตึกเดิมในปี 2015

ทางซ้ายคือตึกใหม่

และในปี 2018 Google ก็กำลังจะสร้างอีกตึกหนึ่งในบริเวณเดียวกัน

ผมก็ยังสงสัยเหมือนกันว่า Disaster Recovery ของ Google Cloud คืออะไร ถ้ามีภัยธรรมชาติในบริเวณนั้นน่าจะไปพร้อมกันทั้ง 3 ตึก

Link Layer Encryption

ในปี 2013 ข่าวใหญ่อันหนึ่งคือ Edwards Snowden ได้เปิดเผยว่า NSA และ GCHQ ได้ดักฟัง Fiber ใต้น้ำระหว่างศูนย์ข้อมูลของ Google และต่อมา Google ก็เร่งเข้ารหัสข้อมูลระหว่างศูนย์ข้อมูล

ข่าวเหล่านี้ยิ่งทำให้เราเห็นว่าการอยู่บน Cloud ยิ่งทำให้เราเป็นเป้าหมายในการดักฟัง เพราะถ้าหากดักฟัง Cloud ได้แล้วก็จะได้ข้อมูลของลูกค้าจำนวนมากไปด้วย

ปัจจุบัน Cloud ทั้งสองเจ้าจึงระบุว่ามีการเข้ารหัสข้อมูลบน Network แล้ว แต่จะเป็นอย่างไร?

AWS

AWS เพิ่งเปิดเผยระบบ VPC Encryption เมื่อเดือนที่แล้ว

VPC Encryption

Image

โดย Instance ประเภท C5n, I3en, P3dn มีการเข้ารหัสข้อมูลอยู่แล้ว โดยใช้ Hardware เพื่อให้มีประสิทธิภาพสูงสุด

ทั้งนี้ข้อจำกัดของระบบเข้ารหัสอัตโนมัติมีพอสมควรคือ

  1. Instance ทั้งสองฝั่งจะต้องเป็นประเภทที่รองรับเท่านั้น
  2. Instance ทั้งสองฝั่งจะต้องอยู่บน VPC เดียวกัน หรือมี VPC Peering หากันซึ่งไม่ข้าม region

โดยระบบจะเข้ารหัสทั้ง Packet รวมทั้ง Header ของ AWS ด้วย ทำให้เมื่อดักฟังแล้วจะไม่ทราบแม้แต่ว่าเป็นแพคเกจของลูกค้าคนใด

Lever

AWS ยังได้พัฒนาระบบ Lever ที่เข้ารหัสข้อมูลบน Network ขึ้นมาอีกด้วย ซึ่งตอนนี้ผมยังไม่ทราบว่าระบบนี้นำมาใช้ตั้งแต่เมื่อไร

Lever จะเข้ารหัสข้อมูลบน Network ทั้งหมดที่ออกจากที่ตั้งของ AWS (Physical Boundary) ทั้งหมด เช่นถ้าไฟเบอร์วิ่งข้ามถนนไปหรือข้ามน้ำข้ามทะเลก็ตาม ข้อมูลที่วิ่งผ่านจะเข้ารหัสทั้งหมด

แน่นอนว่าทั้งหมดนี้ผู้ใช้งานไม่ต้องทำอะไรเลย

Google Cloud

Google ออก Whitepaper ด้าน Security มาหลายอัน ซึ่งผมแนะนำให้อ่านเพราะสามารถนำมาปรับใช้กับงานของเราได้

  • Google Security เล่าถึงนโยบายการปฏิบัติงานของ Google
  • Encryption at Rest เล่าถึงข้อมูลของเราว่าถูกจัดเก็บไว้อย่างไร
  • Encryption in Transit ซึ่งจะมาเล่าให้ฟัง

ใน Whitepaper นี้ Google ระบุว่า Traffic จะถูกเข้ารหัสก็ต่อเมื่อ

  • Traffic วิ่งออกจากที่ตั้งของ Google (Physical Boundary)
  • Traffic นั้นเป็นการใช้ Private IP คุยกัน
  • ทั้งสองฝั่งอยู่บน VPC เดียวกัน หรือ VPC Peering กัน

นอกจากการเข้ารหัสแล้ว ระบบ SDN ของ Google ยังจะมีการ Authenticate traffic ด้วย ทำให้ไม่สามารถ spoof network traffic ได้

สรุป

จากที่เรารีวิวมาก็จะเห็นว่าทั้งสอง 2 cloud จะมีการเข้ารหัสข้อมูลให้อัตโนมัติเมื่อวิ่งออกจากศูนย์ข้อมูลแห่งหนึ่งไปอีกแห่งหนึ่ง แต่ภายในศูนย์ข้อมูลเดียวกันนั้นก็ยังไม่มีการเข้ารหัสเพื่อลด overhead ลง จะมีแต่เฉพาะ AWS เท่านั้นที่มีการเข้ารหัสภายในศูนย์ข้อมูล แต่ก็จำกัดเฉพาะ instance type บางประเภทเท่านั้น

Wall of Text #6: When O(1) doesn’t matter

ไม่แน่ใจว่าเปิดประเด็นนี้มาได้ยังไง

ตอนเรียนปีสองจะมีวิชา Data Structure ซึ่งเราจะได้เรียนว่า Data Structure ต่างๆ มี Time complexity เท่าไร ทวนให้อีกครั้งหนึ่งคือ

ArrayList (Vector) คือการสร้าง Array ขึ้นมาเก็บข้อมูล ดังนั้นการเข้าถึงสมาชิกใดๆ ใน Array เป็น O(1) แปลว่าไม่ว่าจะเข้าตัวไหนก็ใช้เวลาเท่ากันหมด

แต่ถ้าหากต้องการเพิ่มสมาชิกของ Array แล้ว มีโอกาสที่ Array เต็มซึ่งจะต้องสร้าง Array ใหม่ที่ใหญ่ขึ้นแล้ว copy ข้อมูลเก่าลงไป ดังนั้นเวลาที่ใช้คือ O(n) หรือแปลผันตามจำนวนสมาชิกของ Array

LinkedList เป็นการสร้างระเบียนข้อมูล 1 ชุด ในระเบียนจะเก็บข้อมูล, ที่อยู่ (Pointer) ของระเบียนถัดไป และถ้าเป็น Doubly Linked List จะมีที่อยู่ของระเบียนก่อนหน้าด้วย

การเข้าถึงสมาชิกใน LinkedList จึงต้องกระโดดจากระเบียนหนึ่งไปอีกระเบียนหนึ่ง ถ้าหากต้องการเข้าถึงระเบียนสุดท้ายก็ต้องใช้เวลา O(n) คือกระโดดผ่านทุกสมาชิก

วิธีที่จะทำให้เร็วขึ้นคือ เก็บทั้งตัวแรกและตัวสุดท้ายไว้ ตัวที่จะเข้าถึงช้าสุดก็คือตัวตรงกลางแทน วิธีนี้ก็ยังเขียนสัญกรณ์ Big O เป็น O(n) อยู่ดี

แต่ถ้าต้องการเพิ่มสมาชิกเข้าไป เราเพียงแค่สร้างช่องใหม่และเพิ่มตัวชี้เข้าไปยังระเบียนสุดท้ายของเดิม เป็นอันเรียบร้อย แบบนี้จะเป็น O(1)

จากข้อสรุปนี้เราก็จะทราบว่า ถ้าข้อมูลที่ต้องการเพิ่มต่อท้ายบ่อยๆ ใช้ LinkedList จะเร็ว นอกเหนือจากนั้นแล้วใช้ ArrayList ดีกว่า


แต่ตอนปีสามผมได้ฟัง Talk ของ James Gosling ผู้สร้างภาษา Java (เสียดายที่หาไม่เจอแล้ว) เค้าบอกว่าคุณไม่ควรใช้ LinkedList เลย ให้ใช้ ArrayList เสมอ

เพราะอะไร? คำตอบสั้นๆ คือ CPU Cache

ตอนนั้นผมได้ยินแล้วรู้สึกตื่นเต้นมาก เพราะมันคือศึกระหว่างวิชา Data Structure กับวิชา Computer Architecture เลยทีเดียว

Benchmark

เว็บไซต์ DZone ได้ทดลองวัดผลดูแล้ว (แนะนำให้ดูกราฟจากต้นทาง) พบว่าการแทรกสมาชิกใหม่ที่เราทราบดีว่า LinkedList เป็น O(1) นั้นกลับช้ากว่า ArrayList!

สิ่งที่เกิดขึ้น เค้าอธิบายว่าเนื่องจากว่า RAM ทำงานได้ช้า CPU จึงจะนำข้อมูลบางส่วนใน RAM เข้ามาพักบน Memory ที่อยู่บน CPU หรือเรียกว่า CPU Cache

แล้วการเลือกข้อมูลที่จะมาพักทำอย่างไร? วิธีที่ CPU ทำคือเมื่อมีการเข้าถึงข้อมูลที่ไม่อยู่บน Cache แล้ว CPU จะดึงข้อมูลนั้นจากใน RAM เข้ามา และข้อมูลที่อยู่โดยรอบด้วย

ดังนั้น Array ซึ่งเก็บข้อมูลเป็นชุดติดกันจึงได้ประโยชน์จากกระบวนการนี้มาก เพราะเมื่อเราเข้าถึงสมาชิกตัวหนึ่งแล้ว CPU จะดึงตัวติดกันมาด้วย ถ้าเราวนไล่สมาชิก Array ก็จะทำงานได้เร็วมาก สมบัตินี้เรียกว่า Locality

ในขณะเดียวกัน ถึงแม้ว่าการหาสมาชิกตัวถัดไปของ LinkedList จะเป็น O(1) เช่นกัน แต่จะใช้เวลานานกว่ามาก เพราะแต่ละระเบียนไม่ได้อยู่ติดกัน CPU จะต้องดึงข้อมูลจาก RAM ใหม่ทุกครั้ง

จากการทดสอบแล้วก็จะพบว่า overhead ตรงนี้ของ LinkedList แค่จะเปิดหาตัวสุดท้ายมาเพิ่มระเบียนใหม่ก็ช้ากว่า Copy Array แล้ว

ทั้งนี้ถ้า Array มีข้อมูลใหญ่มากๆ ก็ยังอาจจะแพ้ LinkedList อยู่ดีเพราะประสิทธิภาพของ LinkedList ไม่ได้ขึ้นอยู่กับขนาดของข้อมูลเลย ขึ้นอยู่กับจำนวนข้อมูลเท่านั้น

Don’t Premature Optimize

คำแนะนำหนึ่งที่ผมชอบคือ “Premature optimization is the root of all evil” อย่ามัวพะวงว่าโปรแกรมเราช้าเพราะเรื่องเล็กๆ แบบนี้ เพราะบางทีเรา optimize ตรงนี้เป็นอย่างดีแล้วอาจจะเร็วขึ้นแค่ 3% ก็ได้แต่เสียเวลาทำไปหลายวัน

ถ้าอยากจะ optimize ควรจะต้องวัดผลจากการใช้งานจริงให้รู้แน่เสียก่อนว่าตรงไหนช้า ถึงจะ optimize ได้ถูกจุด