การเชื่อมต่อ SSH ผ่าน HTTPS
(trofi.github.io)- แม้พอร์ต
SSHจะถูกบล็อกในเครือข่ายที่มีข้อจำกัด ก็สามารถสร้างเส้นทางเชื่อมต่อระยะไกลได้ด้วย พอร์ต HTTPS 443 และเมธอดCONNECT - ฝั่งเซิร์ฟเวอร์เปิด
CONNECTด้วยmod_proxy_connectของapache2แต่จำกัดขอบเขตพร็อกซีให้แคบลงโดยอนุญาตเฉพาะเป้าหมาย ssh-server:22 - ฝั่งไคลเอนต์เชื่อม ProxyCommand ของ OpenSSH เข้ากับ
socatและในกรณี HTTPS สคริปต์จะส่งเฮดเดอร์CONNECTโดยตรง - ไฟร์วอลล์หรือ
httpdบางตัวอาจปิดการเชื่อมต่อที่ไม่ได้ใช้งาน จึงใช้ServerAliveInterval 30เพื่อช่วย รักษาเซสชัน - วิธีนี้ห่อหุ้ม
SSHไว้ในTLSทำให้หลบเลี่ยงการบล็อกได้ง่ายขึ้น แต่ยังมีภาระเรื่อง การเข้ารหัสซ้อนสองชั้น และการตั้งค่าฝั่งไคลเอนต์
การสร้างเส้นทาง SSH ในเครือข่ายที่ถูกจำกัด
- ในสภาพแวดล้อม Wi-Fi ของโรงพยาบาล การเชื่อมต่อส่วนใหญ่ถูกบล็อก และโดยหลักแล้วอนุญาตเฉพาะ TCP 80 ของ
HTTPและ TCP 443 ของHTTPS - UDP 53 ของ
DNSและ TCP 853 ของDoTดูเหมือนจะใช้งานได้กับผู้ให้บริการ DNS ที่เป็นที่รู้จัก SSHถูกบล็อกทั้งหมดทั้งบน TCP 22 และพอร์ตแบบกำหนดเองส่วนใหญ่- มีการเชื่อมต่อสำรองผ่าน
GSMที่สามารถใช้ตั้งค่าเซิร์ฟเวอร์ระยะไกลใหม่ได้ จึงสามารถทดสอบวิธีเลี่ยงข้อจำกัดหลายแบบได้
การใช้พอร์ตร่วมกันและการห่อหุ้มโปรโตคอล
- มีวิธีรับ
SSHและHTTPSพร้อมกันบนพอร์ตเดียว แล้วแยกเส้นทางอย่างโปร่งใส- โปรเจกต์ sslh ใช้ฮิวริสติกในการคาดเดาโปรโตคอล แล้วรีไดเรกต์ไปยังแบ็กเอนด์จริง เช่น
SSH,HTTPSหรือโปรโตคอลที่รองรับ - ข้อดีคือไม่ต้องตั้งค่า
sshไคลเอนต์เป็นพิเศษ เพียงระบุพอร์ตที่ไม่ใช่พอร์ตเริ่มต้นก็พอ - ข้อเสียคือต้องตั้งค่าบริการเพิ่มเติม,
HTTPSก็ต้องผ่านsslhด้วย และที่แบ็กเอนด์ ที่อยู่ต้นทาง ของการเชื่อมต่ออาจถูกซ่อนไว้ ทำให้การบันทึกล็อกไม่สะดวก
- โปรเจกต์ sslh ใช้ฮิวริสติกในการคาดเดาโปรโตคอล แล้วรีไดเรกต์ไปยังแบ็กเอนด์จริง เช่น
- อีกทางเลือกหนึ่งคือการ ห่อหุ้ม โปรโตคอลหนึ่งไว้ภายในอีกโปรโตคอลหนึ่งอย่างสมบูรณ์
ProxyCommandของ OpenSSH ช่วยให้ผู้ใช้กำหนดตัวกลางส่งข้อมูลที่โปรโตคอลsshจะใช้ได้- เพราะห่อ
SSHไว้ในสตรีมอื่นโดยไม่ต้องใช้ฮิวริสติก จึงอาจทำให้ซอฟต์แวร์ DPI บล็อกได้ยากขึ้น HTTPSเองจะไม่ถูกรีไดเรกต์หรือได้รับผลกระทบ- แต่ประสิทธิภาพอาจลดลงจาก การเข้ารหัสซ้อนสองชั้น และต้องมีการตั้งค่าฝั่งไคลเอนต์
การตั้งค่า SSH over HTTP
- เริ่มจากทดลองวิธีส่ง
SSHผ่านHTTP - การตั้งค่า
apache2ฝั่งเซิร์ฟเวอร์โหลดmod_proxy_connectและใช้AllowCONNECT 22เพื่ออนุญาต CONNECT ไปยังพอร์ต 22 <Proxy *>จะปฏิเสธทั้งหมดโดยค่าเริ่มต้น และอนุญาตเฉพาะ<Proxy ssh-server>เพื่อจำกัดเป้าหมายไว้ที่ssh-server:22.ssh/configฝั่งไคลเอนต์ใช้PROXY:http-server:%h:%p,proxyport=80ของsocatในProxyCommand- ด้วยการตั้งค่านี้ เมื่อรัน
$ ssh ssh-via-httpจะสามารถเชื่อมต่อSSHผ่าน พอร์ต 80 ได้ ServerAliveInterval 30จะส่งโพรบเป็นระยะ เพื่อหลีกเลี่ยงกรณีที่การเชื่อมต่อHTTPที่ไม่ได้ใช้งานถูกปิดเงียบ ๆ ระหว่างทางhttpdค่าเริ่มต้นใช้TimeOut 60ซึ่งจะปิดทันเนลเมื่อไม่มีอินพุต/เอาต์พุตต่อเนื่องเป็นเวลา 60 วินาที
การตั้งค่า SSH over HTTPS
- พบว่า
socatไม่รองรับพร็อกซีHTTPSผ่านเมธอดCONNECTและรองรับเฉพาะHTTP - จึงใช้ความสามารถ TLS encapsulation ของ
socatแทน และให้สคริปต์เป็นผู้สร้างคำขอแบบCONNECTโดยตรง ~/.ssh/https-tunnel.bashทำงานตามลำดับดังนี้- พิมพ์เฮดเดอร์
CONNECT ssh-server:22 HTTP/1.1และHost: ssh-serverก่อน - จากนั้นต่อข้อมูลจาก standard input เข้าไปตามเดิม
- ส่งสตรีมทั้งหมดไปยัง
socat - "SSL:$3:$4"เพื่อสร้าง การเชื่อมต่อ TLS
- พิมพ์เฮดเดอร์
- ใน
.ssh/configกำหนดProxyCommand ~/.ssh/https-tunnel.bashสำหรับHost ssh-via-https - เมื่อรัน
$ ssh ssh-via-httpsก็จะเชื่อมต่อไปยังssh-serverผ่านทันเนลHTTPSได้ตามที่คาดไว้
ข้อควรระวังในการใช้งานจริง
- ในสภาพแวดล้อมที่อนุญาต
HTTPSอย่างแพร่หลาย วิธีนี้สามารถส่งข้อมูลผ่านอุปกรณ์กลางที่มีข้อจำกัดเข้มงวดมากได้ - เมธอด
CONNECTอาจดูเหมือนร่องรอยจากยุคเก่า แต่มีประโยชน์ในการห่อ สตรีมเพย์โหลด TCP ใด ๆ ไว้ในสตรีมของโฮสต์TLS ServerAliveIntervalช่วยรักษาการเชื่อมต่อ OpenSSH เมื่อชั้นขนส่งด้านล่างไม่เป็นมิตรกับการเชื่อมต่อที่ไม่ได้ใช้งาน- ตัวอย่างการตั้งค่าแบบ
nginxอยู่ที่ CONNECT passthrough on nginx
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ประเด็นในบทความที่ว่า “HTTPS มีอยู่ทุกที่ จึงทำให้อุปกรณ์ตัวกลางที่จำกัดมาก ๆ ก็ยังปล่อยให้ข้อมูลผ่านได้” นั่นแหละคือเหตุผลที่แทบทุกโปรโตคอล VPN แบบ proprietary หรือที่เรียกกันว่า “SSL VPN” ต่างก็มีโหมดที่เปิด tunnel ผ่าน HTTPS
แม้จะไม่ใช่พฤติกรรมเริ่มต้น อย่างน้อยก็จะมีไว้เป็นเส้นทางสำรอง โดยมีเป้าหมายเพื่อให้มีโหมดที่ใช้งานได้กับแทบทุกการเชื่อมต่อบนอินเทอร์เน็ตทั่วโลก
ผมเป็นหนึ่งในนักพัฒนาหลักของ https://gitlab.com/openconnect/openconnect ซึ่ง implement โปรโตคอล VPN ที่อิง TLS หลายแบบ และยังสร้าง https://github.com/dlenski/what-vpn สำหรับตรวจจับและระบุชนิดของเซิร์ฟเวอร์ VPN ที่อิง TLS ได้มากขึ้นด้วย
เมื่อก่อนผู้ให้บริการอินเทอร์เน็ตในเนเธอร์แลนด์ชื่อ XS4ALL เคยให้ฟีเจอร์แบบนี้พอดี
เขาเปิดให้เชื่อมต่อ SSH ทางพอร์ต 80 และเคยช่วยได้หลายครั้งตอนเดินทางแล้ว WiFi โรงแรมบล็อกทุกอย่างยกเว้นพอร์ต 80
แต่ในมุมของ KPN ก็คงไม่ค่อยสบายใจกับวัฒนธรรมแฮกเกอร์ของ XS4ALL มาตั้งแต่แรกแล้ว
ให้ความรู้สึกเหมือนการกลับมาของวัฒนธรรมวิทยุโจรสลัดในทศวรรษ 1960
https://en.wikipedia.org/wiki/Pirate_radio_in_Europe
https://www.shodan.io/search/facet?query=ssh&facet=port
https://www.shodan.io/search/facet.png?query=ssh&facet=port
ขณะที่พอร์ต 80 พบได้น้อยกว่ามาก
จำได้ว่าเมื่อก่อนเคยใช้แค่ในฐานะผู้ให้บริการ newsgroup
มักมีตัวเลือกที่สามด้วย: เปิด SSH ไว้บนพอร์ต 80 หรือ 443 ของโฮสต์อื่น แล้วใช้ ProxyJump จากตรงนั้นไปยังปลายทาง
หรือจะเปิด SOCKS ไปยังโฮสต์นั้น เพื่อให้ได้การเชื่อมต่ออินเทอร์เน็ตที่โดยรวมถูกกรองน้อยลงก็ได้
ผมใช้ SOCKS และส่ง DNS ที่อิง TLS ผ่าน port forwarding ของการเชื่อมต่อ SSH ด้วย
เมื่อหลายปีก่อน ตอนตั้งค่า SOCKS proxy ครั้งแรกและใช้ WiFi ค่อนข้างมาก ผมยังไม่เคยเจอที่ไหนตรวจเกินกว่าระดับดูพอร์ต แต่เครื่องมือแบบนั้นมีอยู่จริง และตอนนี้อาจพบได้บ่อยขึ้นแล้ว
ดังนั้นผมก็แค่ SSH เข้าเซิร์ฟเวอร์ของตัวเองแล้วใช้งานตามปกติ
ต่อมาผมทำ archive ไฟล์ Windows
.isoแล้วดาวน์โหลดลงแล็ปท็อปและอัปโหลดขึ้นเซิร์ฟเวอร์ด้วยscpปรากฏว่าการใช้ทราฟฟิกรวมอัปโหลด/ดาวน์โหลดหลายสิบ GB บนพอร์ตที่ไม่ใช่ 80/443 คงมากพอให้เกิดการตรวจสอบทราฟฟิก ช่วงเที่ยงฝ่าย IT เลยบล็อกพอร์ต 22แต่เพราะเขาไม่ได้บล็อกพอร์ตอื่น ผมจึงย้าย SSH ไปที่ 443 ด้วย port forwarding แล้วใช้ต่อ
หลังจากนั้นฝ่าย IT ของโรงเรียนจับได้ว่ามีการใช้ SSH บน 443 จึงใส่การวิเคราะห์ทราฟฟิกพื้นฐานเพื่อบล็อก SSH บน 80/443 แต่พอร์ตอื่นทั้งหมดก็ยังเปิดอยู่
สุดท้ายพวกเขาบล็อกเซิร์ฟเวอร์ของผมตาม IP แต่ IP อื่นทั้งหมดยังเปิดอยู่
ถ้าใช้ ProxyJump ผ่าน VPS ก็น่าจะเลี่ยงได้ แต่เพราะเป็นหลักสูตรมัธยมปลายแบบ early college หลังขึ้นปี 2 ผมแทบไม่ได้ไปโรงเรียนแล้ว เลยไม่ค่อยคุ้มที่จะลงแรง
ครั้งหน้าที่ไป ผมคิดว่าจะลองทำเพื่อพิสูจน์ว่าทำได้ และถ้าบล็อก SSH ทุกพอร์ต ก็แค่ตั้ง SSH over HTTPS ไว้บน VPS
หลังเรียนจบ ผมคิดว่าจะกลับไปดูอีกทีว่า guest WiFi ทำอะไรได้ถึงไหน
อาจเป็นการโปรโมตที่ค่อนข้างตรงไปหน่อย แต่ที่ Adaptive [1] เรากำลังสร้างโครงสร้างพื้นฐานความปลอดภัยของข้อมูลอยู่
หนึ่งในผลิตภัณฑ์ของเราส่ง SSH และโปรโตคอลอื่น ๆ หลายแบบผ่าน HTTP/3 ทำให้ผู้ใช้เชื่อมต่อกับฐานข้อมูล เซิร์ฟเวอร์ และทรัพยากรอื่น ๆ ได้ผ่าน outbound port เดียว
คล้าย ๆ พวก Ngrok แต่ self-host ได้ และสามารถเข้าถึงแบบไม่ใช้รหัสผ่าน หรือใส่ credential ชั่วคราวกับการป้องกันแบบ maker-checker ได้
[1] https://adaptive.live/
ในทางปฏิบัติ แค่ให้
opensshlisten ที่พอร์ต 443 ก็สามารถเลี่ยง firewall ส่วนใหญ่ได้แล้วดีเลย แปลกที่ผมไม่เคยคิดถึงเมธอด
CONNECTในแบบreverse proxy แทนที่จะเป็น forward proxy มาก่อนแต่ในกรณีของผม
CONNECTอย่างเดียวไม่พอ จึงใช้ SSH บน WebSocket เพื่อทะลุ proxy ของบริษัทproxy นั้นตรวจสอบการเชื่อมต่อ HTTPS ด้วย CA ที่กำหนดเอง
ผมแก้
socatเพื่อให้บริการเซิร์ฟเวอร์ SSH ของผมผ่าน Apache เป็น WebSocket และฝั่ง client ใช้ร่วมกับProxyCommandของ OpenSSHคิดอยู่ว่าควรอัปโหลด patch นั้นสักที แต่ก็มีตัวเลือกอื่นอย่าง
websocatด้วยเกือบ 20 ปีก่อน ผมเคยใช้เครื่องมือ corkscrew[0] ที่ทำสิ่งนี้พอดี เพื่อเจาะรูผ่านไฟร์วอลล์ของบริษัท
ทั้งการทำเป็นโปรแกรมเดี่ยวและบทความเขียนไว้เรียบร้อยดี
0: https://github.com/bryanpkc/corkscrew
corkscrewใช้ได้เฉพาะภายใต้เงื่อนไขบางอย่าง: ต้องอยู่หลัง HTTP proxy และ HTTP proxy นั้นต้องรองรับเมธอดCONNECTตอนที่ผมรับงานสัญญาระยะสั้นเมื่อราว 20 ปีก่อน มีเงื่อนไขแรก แต่ไม่มีเงื่อนไขที่สอง
โชคดีที่มีเครื่องมือที่ใช้ได้แม้ในกรณีแบบนี้ และแน่นอนว่าต้องตั้งค่าฝั่งเซิร์ฟเวอร์ด้วย
https://github.com/larsbrinkhoff/httptunnel
โดยรวมแล้ว การทำ tunneling ผ่าน HTTP/2 พิสูจน์แล้วว่าเป็นตัวเลือกที่ดี
มี gRPC[1] ซึ่งเป็นโปรโตคอล remote procedure call ที่สร้างอยู่บน HTTP/2
เพราะ HTTP/2 เด่นเรื่อง multiplexing ที่ใช้การเชื่อมต่อ TCP เดียวเพื่อรับส่งโครงสร้างข้อมูลหลายชุดพร้อมกัน
อย่างไรก็ตาม QUIC เองก็มี multiplexing อยู่แล้ว จึงอาจไม่มีเหตุผลต้องใช้ HTTP/3 ก็ได้
ต่อไปการสื่อสารส่วนใหญ่น่าจะย้ายไปอยู่บน HTTP/2 และ QUIC ที่เข้ารหัส เพราะผู้ผลิตอุปกรณ์ตัวกลางคงเลิกเลือกปฏิบัติไม่ได้
เพื่อบรรเทา active probing[2] อาจต้องเสิร์ฟคอนเทนต์ HTTP/2·HTTP/3 แบบสุ่ม หรืออาจเป็นคอนเทนต์ที่ AI สร้างขึ้น
[1] <https://grpc.io>
[2] <https://blog.torproject.org/learning-more-about-gfws-active-...>
ตัว HTTP เองก็เป็นโปรโตคอล request/response อยู่แล้ว และโดยพื้นฐานก็ใช้ทำ remote procedure call ได้
ไม่ว่าจะเป็น HTTP 1, 2 หรือ 3 ก็ดูไม่ต่างกันมาก
วิวัฒนาการของโปรโตคอลนั้นเองก็น่าสงสัยอยู่บ้าง และมีส่วนที่ออกแบบมาให้ใช้ประโยชน์จากสิ่งที่ไม่จำเป็นในสภาพแวดล้อม remote procedure call
โดยแก่นแล้วมันเหมือนถูกออกแบบมาเพื่อ อินเทอร์เน็ตสาธารณะ มากกว่าบริการภายในเครื่อง
HTTP/3 ทำงานบน QUIC
ส่วนผมกลับชอบ HTTP บน SSH มากกว่า
พูดกึ่งล้อเล่นนะ แต่ถ้าเบราว์เซอร์มีการจัดการตัวตนระดับเดียวกับ SSH ในตัวก็คงดี
ตอนอ่าน hobo ซึ่งเป็นข้อเสนอการยืนยันตัวตน HTTP ด้วยกุญแจสาธารณะครั้งแรก ผมตื่นเต้นมาก แต่ก็พบว่าไม่มีทั้ง implementation ฝั่งเซิร์ฟเวอร์และ implementation ฝั่งไคลเอนต์เบราว์เซอร์
มี implementation แบบ JavaScript อยู่ แต่ไม่ใช่รูปแบบที่ผมต้องการ
ssh -D “*:8080” hostคำสั่งนี้จะเปิด SOCKS proxy ที่พอร์ต 8080
ผมใช้ใน Firefox ตลอด และมันทำงานเหมือน VPN รุ่นดั้งเดิม
ใช้กับเรื่องน่าสงสัยก็สะดวก แต่ผมก็ใช้ตอนเข้าถึงแดชบอร์ด rmq ที่อยู่ในเครือข่ายส่วนตัวของ AWS ด้วย
https://techcommunity.microsoft.com/t5/iis-support-blog/clie...
ผมไม่รู้ละเอียดพอว่าตรงกับข้อกำหนดหรือไม่ แต่เคยใช้ยืนยันตัวตนกับเซิร์ฟเวอร์ตอนเรียนมหาวิทยาลัย
ssh://google.comได้ก็คงดีhttps://news.ycombinator.com/item?id=38664729
ทำไม
sslhถึงไม่ได้รับความรักบ้างนะ?มันตรวจจับ HTTP, TLS/SSL (รวม SNI และ ALPN), SSH, OpenVPN, tinc, XMPP, SOCKS5 ได้ และยังรู้จักโปรโตคอลอื่น ๆ ที่ตรวจด้วย regex ได้ด้วย
การใช้งานทั่วไปคือให้บริการหลายอย่างร่วมกันบนพอร์ต 443
เช่น สามารถเชื่อมต่อ SSH จากหลังไฟร์วอลล์บริษัทได้ ขณะเดียวกันก็ยังให้บริการ HTTPS บนพอร์ตเดียวกันต่อไป
https://www.rutschle.net/tech/sslh/README.html
sslhหรือ การ encapsulation แบบสมบูรณ์เหตุผลที่เลือก encapsulation แบบสมบูรณ์ดูเหมือนจะเป็นเพราะมีบริการให้ตั้งค่าน้อยลงหนึ่งตัว, HTTP server เป็นตัวจัดการการเชื่อมต่อจึงได้ที่อยู่รีโมตในล็อกอย่างถูกต้อง, และอาจเพราะตามจิตวิญญาณแฮ็กเกอร์แล้วชอบวิธีใหม่มากกว่าวิธีเดิม