SSH agent của VSCode thật khó hiểu
(fly.io)- Fly.io từng muốn tích hợp vào luồng chỉnh sửa SSH từ xa của VSCode, nhưng phát hiện VSCode không chỉ tận dụng nhẹ nhàng shell từ xa mà dùng cấu trúc cài đặt và chạy một agent riêng
- Việc sinh mã bằng LLM hữu ích hơn trong một vòng lặp agent nối với môi trường chạy, nhưng vì nó có thể động chạm cả đến thiết lập hệ thống của laptop phát triển, nên cần một instance Linux được cô lập
- Tramp của Emacs mở rộng chức năng sang môi trường từ xa bằng cách chạy các lệnh Bourne shell trong môi trường tương tác như SSH, còn VSCode tải xuống agent và binary Node bằng một Bash snippet stager
- Agent của VSCode chạy trên SSH được chuyển tiếp cổng, thiết lập kết nối WebSockets với frontend VSCode, và có thể duyệt tệp, chỉnh sửa tệp tùy ý, chạy shell PTY, cũng như tự duy trì sự tồn tại
- Chỉ riêng việc cho phép chỉnh sửa từ xa bằng VSCode trên máy chủ phát triển đã là một gánh nặng lớn; nếu cách này được dùng trong sự cố production thì càng đáng lo hơn, nhưng với kết nối tùy chỉnh cho Fly Machine thì họ đã có thể tránh cấu trúc này
Sự cô lập cần thiết cho vòng lặp agent LLM
- Fly.io quan tâm đến việc tích hợp với luồng VSCode chỉnh sửa từ xa qua SSH
- Vì có nhiều người dùng VSCode, đặc biệt là các fork của VSCode dùng LLM để sinh mã
- Mã do LLM sinh ra hữu ích khi nó biết người dùng đang làm gì, và còn hiệu quả hơn nếu có thể khép kín vòng lặp với môi trường thực thi
- LLM sinh mã
- Phần scaffolding của agent chạy mã đó
- Mã tạo ra lỗi
- Agent chuyển lỗi lại cho LLM
- Quá trình này lặp lại
- Cấu trúc này có thể là một liều giải độc hiệu quả một phần cho hiện tượng ảo giác, nhưng sẽ nguy hiểm nếu chạy nguyên xi trên laptop phát triển
- LLM có thể liên tục động chạm không chỉ dự án Git đang làm việc mà cả thiết lập hệ thống
- Hình thức tốt hơn là chạy cấu hình agent dạng vòng lặp khép kín trên một instance Linux sạch được khởi động tức thì, đồng thời ngăn môi trường đó gây hại cho người dùng
Cách agent SSH từ xa của VSCode hoạt động
- Tramp của Emacs là mã Elisp gần như tổ tiên tinh thần của các hệ thống chỉnh sửa từ xa
- Khi gắn vào một môi trường tương tác có thể chạy lệnh Bourne shell, như một phiên SSH, nó mở rộng chức năng của Emacs sang môi trường đó
- VSCode cũng có chức năng tương tự Tramp, nhưng không phải là một phiên bản Tramp đơn giản hóa được chuyển sang TypeScript
- Thay vì chỉ dùng các công cụ sẵn có trong kết nối từ xa, VSCode chạy một Bash snippet stager để tải agent xuống
- Agent này bao gồm một bản cài binary của Node
- Vị trí có vẻ là mã nguồn liên quan là thư mục server/node của microsoft/vscode
- Agent hoạt động trên SSH được chuyển tiếp cổng, và tạo kết nối WebSockets tới frontend VSCode đang chạy
- Giao thức con có thể đi lại trong filesystem
- Có thể chỉnh sửa tệp tùy ý
- Có thể chạy tiến trình shell PTY của riêng nó
- Có thể tự duy trì chính nó
- Có một tên gọi trong ngành bảo mật cho công cụ hoạt động theo kiểu này, nhưng bài viết không nói thẳng vì như vậy sẽ không công bằng với VSCode
- Việc cho phép chỉnh sửa từ xa bằng VSCode trên máy chủ phát triển là điều gây bất an; nếu cùng cách đó được dùng trong một sự cố production thì mối lo còn lớn hơn
- Khi tạo kết nối tùy chỉnh cho Fly Machine, họ không cần bận tâm đến cấu trúc này, nên theo nghĩa sâu xa thì đây không phải là vấn đề quan trọng
1 bình luận
Ý kiến Hacker News
Định viết một bài dài cỡ một tháng về phần mềm đã mày mò suốt 3~4 năm, nhưng Kurt sốt ruột vì từ tháng 8 đến giờ không đăng gì lên blog, nên cuối cùng quyết định viết bài đơn giản nhất có thể
Kiểu như làm ngược lại với những gì vẫn làm bấy lâu nay: viết một bài ít công sức, và nghĩ rằng 30 phút là có thể xong một bài. Đây đơn giản chỉ là viết lại thứ đã mày mò, chắc còn suy nghĩ ít hơn cả người đọc nữa
Câu trong README “A compromised remote could use the VS Code Remote connection to execute code on your local machine.” rõ ràng hơn nhiều, và có cảm giác lưu ý bảo mật này nên đi kèm một mã CVE
Hai bài đang hiện đầu tiên là bài FLAME-Livebook-GPU của McCord-Valim và bài này có chữ “murid”, cho thấy rất rõ quỹ đạo tâm lý của tác giả
Vẫn có thể cho phép binary hệ thống, nhưng như vậy sẽ phức tạp hơn và VSCode có thể phải đẩy nhiều thứ hơn sang phía client. Tìm sơ thì thấy có tùy chọn chroot ở phía ssh server, nhưng trong tài liệu client ssh thì hầu như không thấy nhắc đến
Hoặc một cách giải quyết khác là tải container Docker từ remote xuống, chạy container có mount thư mục remote, rồi ssh vào chính container đó
Vấn đề với cách chỉ đồng bộ tệp trong thư mục con là VSCode còn cần thực thi và debug từ xa sau khi khởi động. Vì thế plugin cũng cần truy cập từ xa hoặc phải chạy ở remote, còn một số kiểu quan sát mã nếu chạy ở local thì chi phí đồng bộ trước toàn bộ thư mục con có thể quá lớn
Nghe có thể hơi ngây thơ, nhưng tôi không thật sự hiểu vì sao đây lại là vấn đề bảo mật. Nếu có thể ssh vào một máy và chuyển tiếp cổng socket, thì về cơ bản bạn đã có quyền làm mọi thứ khác rồi, còn giao thức của VSCode có vẻ chỉ phơi bày điều đó theo cách thuận tiện hơn cho họ
Tôi tự hỏi có phải nó trở thành vấn đề bảo mật vì ai đó ở cùng mạng với máy remote nhưng không có quyền SSH vẫn có thể kết nối vào cổng đã được chuyển tiếp qua SSH hay không. Từ góc nhìn người dùng thì hệ thống SSH của VSCode hoạt động khá tốt nên tôi thích nó
sshhay PuTTYVSCode cài một remote agent lên máy đích, dùng ssh làm giao thức truyền tải, rồi nói rằng sẽ chia sẻ đường truyền đó với người dùng. Nếu chỉ làm đúng việc cần làm thì không sao, nhưng một hệ thống dựa trên agent phơi ra API tùy ý sẽ tạo bề mặt tấn công và rủi ro lớn hơn nhiều so với cách quen thuộc nhưng vẫn khó nhằn là giả lập terminal trên nền ssh
Giao thức trên kết nối đó có thể đi khắp hệ thống tệp, chỉnh sửa tệp tùy ý, dựng tiến trình PTY shell của riêng nó và tự duy trì sự tồn tại. Việc client ssh vào server từ xa không có nghĩa là server đó có thể thực thi mã tùy ý trên client; ít nhất thì client phải chủ động làm một hành động nào đó
Nhưng nó là vấn đề bảo mật theo cùng nghĩa mà “curl | bash” là vấn đề bảo mật. Một phép so sánh gần hơn có lẽ là curl | bash nằm bên trong
bashrcVì agent gắn vào mạng và luôn chạy, nên một lỗ hổng trên tường lửa của server phát triển cũng đồng thời trở thành lỗ hổng trên tường lửa của laptop
Càng biết VSCode hoạt động thế nào, nó càng trông như chỉ vừa đủ được chắp vá lại bằng băng keo và những ý tưởng bị nguyền rủa nhất mà một lập trình viên JavaScript có thể nghĩ ra
Chỉ riêng extension SSH thôi đã có hai định dạng URI workspace. Một loại thực chất chỉ có hostname, còn loại kia là tài liệu JSON được mã hóa hex; loại sau được dùng khi cần thêm thông tin như username cụ thể hoặc khi hostname có chữ hoa
Lý do thực sự cần điều này là vì khi được lưu vào workspace gần đây, không hiểu sao nó lại bị chuyển thành chữ thường
Kết nối SSH cũng hỗ trợ cấu hình extension sẽ cài lên server, nhưng nếu nhét quá nhiều vào thì sẽ không thể kết nối tới host Windows. Nó truyền qua CMD dưới dạng tham số dòng lệnh, mà CMD có giới hạn 8191 ký tự, rồi từ CMD lại gọi PowerShell
Có thể cung cấp tự động hoàn thành tùy chỉnh, chẩn đoán, v.v., và cũng có thể làm Go to definition tùy chỉnh để hỗ trợ giữa nhiều ngôn ngữ
Giá mà Microsoft thuê tôi vài tháng, cho ngồi một góc để gỡ mớ hỗn độn này thì tốt biết mấy
Tôi từng vận hành máy chủ cho các lớp về mạng, khai thác nhị phân và lập trình hệ thống nhập môn, và thứ này là một cơn đau đầu lớn. Con ngựa thành Troia truy cập từ xa ngu ngốc này khiến sinh viên không hiểu cách dùng OpenSSH client
Tôi đã thử vài cách để khắc phục. Tôi ghi trong motd của máy chủ lớp học là đừng dùng plugin máy chủ từ xa của VSCode, và trước lớp tôi chạy
ncdu /homeđể cho thấy những sinh viên có mức dùng đĩa trên máy chủ vượt 100MB thì không ngoại lệ đều là người dùng VSCodeTôi cũng đặt giới hạn tiến trình người dùng là 45, vì không hiểu sao con ngựa thành Troia truy cập từ xa của VSCode lại dùng khoảng 50 tiến trình Node. Nếu sinh viên phớt lờ motd và cảnh báo trong giờ học thì họ sẽ đụng giới hạn, rồi phải nhờ chúng tôi giết tiến trình để có thể đăng nhập lại
Cuối cùng tôi bỏ giới hạn tiến trình và thay bằng một script giết toàn bộ con ngựa thành Troia truy cập từ xa
.vscode-servermỗi 10 giâyỞ lớp tôi từng làm trợ giảng, có bài tập xử lý ngôn ngữ máy cơ bản để mô phỏng công cụ lắp ráp/chạy cho ISA đã học, và sinh viên phải hiểu cấu trúc byte của file bằng những thứ như
hexdumpNhưng Sublime lại “tử tế” render file đối tượng theo dạng biểu diễn văn bản của hexdump, đồng thời thêm khoảng trắng để dễ đọc, và còn hiển thị theo thứ tự endian khác với khi
hexdumptrên máy chủ Linux của trườngMỗi học kỳ lại có vài sinh viên đến hỏi vì sao code họ viết để đọc chuỗi ASCII như
AD DE EF BElại đi tìm một đoạn văn bản không rõ là gì, trong khi họ chưa hề xác nhận rằng giá trị byte thực sự bắt đầu bằng 0xDE, 0xAD, 0xBE, 0xEFTôi không chắc ở đây lựa chọn thay thế là gì. Chỉnh sửa qua SSH của VSCode hoạt động tốt đến mức đáng ngạc nhiên, còn việc mò mẫm với vim, nano hay micro trên máy từ xa thì tôi đã bỏ từ lâu
Agent này cho phép tôi làm việc âm thầm mà không bị cản trở. Cảm giác gần như đang làm trên máy cục bộ, và với tôi đó là một điểm cộng lớn
Nó có thể là một rủi ro bảo mật, nhưng về trải nghiệm phát triển thì không có gì sánh được. Tôi cũng không mấy quan tâm VSCode đang giết chết editor nào khác, chỉ cần công cụ đừng cản trở và để tôi làm việc là được
Nó không triển khai binary, mà đọc ghi byte qua pipe, và mọi thực thi có ý nghĩa đều diễn ra ở máy cục bộ. Đặc biệt là nó không tạo ra tính dai dẳng; “plugin VSCode có thể truy cập trong lúc đang kết nối qua SSH” khác với “plugin VSCode có thể truy cập mãi mãi”
Khi làm việc với nhiều remote, họ thường không biết mình đang nối vào đâu và trạng thái kết nối thế nào. Terminal thì chậm và khả năng duy trì trạng thái phiên thì lúc được lúc không
Đây là trải nghiệm tệ hơn rất nhiều so với dùng
tmuxvà một trình soạn thảo văn bản tử tế. Chưa kể server rất nặng và không tắt đúng cách, nên việc chạy tới sáu instance server là chuyện thườngMột nửa số lần cập nhật bị lỗi, và họ có thể mất cả tiếng vì không biết cách dùng ssh client thật để vào host và dọn dẹp máy chủ vscode bị hỏng
Rốt cuộc đã học được gì? Rằng thực thi mã từ xa là có thật? Rằng niềm tin đặt nhầm vào công cụ phát triển thường khiến người ta phải hối hận? Rằng thiết kế phần mềm hiện đại là một mớ hỗn độn? Chỉ cần cẩn thận hơn một chút thì tất cả đều đã quá rõ ràng
SSH là lời giải của thập niên 90. Nó là Telnet với vài tính năng được thêm vào, và dù được gọi là shell “secure”, xét theo nghĩa đen nó còn kém an toàn hơn Telnet+TLS
Vì đã có sẵn một đường hầm với phiên người dùng trên máy chủ, người ta kết luận rằng không cần tạo riêng cơ chế truyền mạng và giao thức kết nối an toàn cho ứng dụng, rồi chất lên trên SSH đủ thứ kỳ quặc nhưng lại được tung hô
Đây là kết quả của việc vứt bỏ những khái niệm học được từ hệ điều hành phân tán, phớt lờ các cơ chế xác thực và phân quyền tiên tiến đã được phát triển, rồi chấp nhận thứ tệ nhất nhưng dễ nhất
Việc có một “SSH agent” như thế này không phải là điều vô lý. Chúng ta đã không cố tạo ra công cụ đúng cho đúng công việc, nên cứ tiếp tục nhồi thêm vào những công cụ cũ vốn không được thiết kế cho mục đích đó. Chúng ta không có quyền giả vờ ngạc nhiên
Đây là thế giới do chính chúng ta tạo ra. Dù bằng lao động hay bằng sự đồng lõa trong im lặng, tất cả đều góp phần tạo nên nó. Không chỉ với SSH, mà cả chính trị, thương mại, trường học và mọi thứ khác cũng vậy. Mỗi ngày ta sống trong đống hỗn độn do chính mình chất lên, và mỗi ngày không làm gì thì coi như lại xúc thêm một xẻng nữa. Cầm xẻng trên tay mà còn giả vờ đây là điều bất ngờ hay điên rồ thì không được
Vì vậy, nếu nhìn chung đã cho phép các kết nối HTTPS đi ra ngoài, thì về cơ bản cũng nên cho phép mọi kết nối đi ra ngoài trừ SMTP. Lưu lượng độc hại thực tế đằng nào cũng sẽ tunnel qua HTTPS, và tác dụng còn lại chỉ là cản trở việc triển khai các giao thức mới khỏi phải gánh sự phức tạp và kém hiệu quả của đường hầm
Tôi cũng mong đăng nhập web gần với cách SSH làm hơn
Thỉnh thoảng ra ngoài chạm cỏ một chút cũng tốt cho tâm hồn. Và cũng mong bạn đề xuất cách làm một giao thức SSH tốt hơn. Than phiền mà không có phê bình mang tính xây dựng thì không giúp ích mấy
Ở đây, thuật ngữ “SSH agent” khá gây nhầm lẫn. Thông thường nó chỉ một daemon dùng để cache token xác thực
Hơn nữa cách đó còn làm hỏng SSH agent nổi tiếng trên macOS: https://github.com/maxgoedjen/secretive/issues/543
Tôi hoàn toàn đồng ý rằng dùng vscode remote trên máy chủ vận hành là chuyện điên rồ
Tuy vậy, những tính năng còn lại bị mô tả là “vớ vẩn” thì lại nghe giống các tính năng có thể mong đợi
Tôi đã lên đến mức staff engineer ở MAANG, và nghĩ rằng đó là mức độ khó đạt được chỉ với Vim thuần túy. Nhưng tôi cũng thấy nhiều người có hiệu suất cao khác vẫn có xu hướng dùng Vim hoặc Emacs
Có rất nhiều lập trình viên giỏi dùng VCode, JetBrains, v.v., nhưng tôi nghĩ hiện tượng này được giải thích tốt hơn bởi xu hướng đi tìm rào cản gia nhập, bóc tách “phép thuật” của công cụ thông qua khám phá, và coi trọng các dự án hoàn toàn mã nguồn mở, có thể tùy biến sâu, do cộng đồng dẫn dắt, hơn là bởi tính năng hay độ tiện dụng
Càng đọc về độ phức tạp của chỉnh sửa từ xa trong VSCode thì tôi càng ít muốn dùng VSCode hơn. Cứ ssh vào máy rồi dùng trình soạn thảo có sẵn trên máy đó là được
Cách giải quyết của VSCode thì hoạt động, nhưng không thanh lịch, cũng không áp dụng phổ quát, và còn dễ hỏng hơn. Và xin lỗi người dùng Emacs, nhưng Tramp vẫn khá kinh khủng, còn netrw cũng chẳng khá hơn
watchexec+rsyncCó thể theo dõi các đường dẫn tệp cụ thể và chỉ đồng bộ chính xác những gì cần thiết. Bạn vẫn làm việc trên hệ thống tệp cục bộ nên không có độ trễ khi chỉnh sửa, có thể dùng toàn bộ công cụ cục bộ, và việc đồng bộ hoàn tất trong vài mili giây
Bạn có thể khiến các tệp xóa ở máy cục bộ cũng bị xóa ở máy từ xa, và luôn giữ lại một bản sao cục bộ sau khi làm việc xong với máy từ xa. Đó là phần mà với Tramp tôi luôn phải đồng bộ thủ công. Hơn nữa nó không phụ thuộc vào trình soạn thảo
Tính năng này của VS Code, giờ khi đã biết nó thực sự làm gì, khiến tôi thấy bất an
Khi bật Copilot, thanh công cụ lại nhiều hơn và văn bản bay vào đúng chỗ tôi đang định gõ. Vim thì chỉ cho tôi nhìn mã, suy nghĩ và viết. Với VSCode, rất khó để vào được trạng thái tập trung sâu
Tôi đang ở giữa tuổi 30, hồi đại học dùng emacs rồi chuyển sang vim ở công việc đầu tiên. Tôi có dùng IntelliJ cho một dự án Java cực kỳ rối rắm, còn ngoài ra thì vẫn dùng vim
Chỉ thỉnh thoảng cần xử lý regex phức tạp thì tôi mới mở vim
Thay vì hoạt động cùng các công cụ truy cập từ xa hiện có, VSCode triển khai một tác nhân toàn diện bao gồm cài đặt binary Node.js, kết nối WebSocket chạy về frontend của VSCode, và khả năng truy cập hệ thống trên diện rộng
Tác nhân VSCode này có quyền rất rộng, bao gồm duyệt hệ thống tệp, chỉnh sửa tệp, tạo tiến trình shell PTY, thậm chí cả khả năng tự duy trì tồn tại
Nếu là từ xa, tôi hiểu elisp Tramp nhẹ hơn về mặt phụ thuộc, nhưng vẫn tự hỏi liệu bề mặt tấn công có thực sự khác biệt đến vậy không. Tức là tôi không biết binary Node từ xa có những quyền mà người dùng chạy lệnh ssh tùy ý không có hay không
Nếu mục tiêu ban đầu là trao cho LLM toàn bộ chìa khóa của một máy ảo tạm thời, có thể vứt bỏ, thì tôi tự hỏi liệu socket mà tác nhân mở ra có nghĩa là nó còn có thể động tới cả máy của lập trình viên mà đáng ra đang được cô lập hay không
Nghe có vẻ điên rồ, nhưng chính kernel có thể cung cấp một web server hoặc giao thức khác với mã hóa và xác thực tích hợp, rồi cho phép điều khiển trực tiếp toàn bộ máy thông qua eBPF. Đây có thể là một mô hình hoàn toàn khác cho điều khiển từ xa kiểu client/server
Tất nhiên, nó cũng có thể trở thành một lỗ hổng bảo mật đủ lớn để Death Star bay qua