Bảo mật thông tin liên lạc trong ứng dụng rail ba tầng sử dụng đường hầm SSH
Các ứng dụng web thường được cấu trúc với ba tầng riêng biệt: Tầng đầu tiên là tầng trình bày , là tầng mà user nhìn thấy. Tiếp theo là lớp ứng dụng , lớp này cung cấp logic nghiệp vụ của ứng dụng. Cuối cùng, lớp dữ liệu lưu trữ dữ liệu mà ứng dụng cần.Các ứng dụng web thường được cấu trúc với ba tầng riêng biệt:
- Tầng đầu tiên là tầng trình bày , là tầng mà user nhìn thấy.
- Tiếp theo là lớp ứng dụng , lớp này cung cấp logic nghiệp vụ của ứng dụng.
- Cuối cùng, lớp dữ liệu lưu trữ dữ liệu mà ứng dụng cần.
Trong một ứng dụng Ruby on Rails , điều này ánh xạ một cách lỏng lẻo tới một web server cho lớp trình bày, một server Rails cho lớp ứng dụng và một database cho lớp dữ liệu. Trong cài đặt này, lớp ứng dụng giao tiếp với lớp dữ liệu để lấy dữ liệu cho ứng dụng, sau đó được hiển thị cho user thông qua lớp trình bày.
Mặc dù có thể cài đặt tất cả các ứng dụng này trên một server duy nhất, nhưng việc đặt từng lớp lên server của chính nó sẽ giúp mở rộng ứng dụng dễ dàng hơn. Ví dụ: nếu server Rails trở thành nút cổ chai, bạn có thể thêm nhiều server ứng dụng hơn mà không ảnh hưởng đến hai lớp còn lại.
Trong hướng dẫn này, bạn sẽ triển khai ứng dụng Rails ở cấu hình ba tầng bằng cách cài đặt một bộ phần mềm duy nhất trên ba server riêng biệt, cấu hình từng server và các thành phần của nó để giao tiếp và hoạt động cùng nhau, đồng thời đảm bảo kết nối giữa chúng bằng các tunnel SSH. Đối với ngăn xếp phần mềm, bạn sẽ sử dụng Nginx làm web server trên lớp trình bày, Puma làm server ứng dụng Rails trên lớp ứng dụng và PostgreSQL làm database trên lớp dữ liệu.
Yêu cầu
Để hoàn thành hướng dẫn này, bạn cần tạo ba server Ubuntu 16.04. Đặt tên cho các web server , server ứng dụng và server cơ sở dữ liệu này và mỗi server phải được bật Mạng riêng.
Mỗi  server  trong số ba  server  phải có  user  không phải root có  quyền  sudo cũng như firewall  được  cấu hình  để cho phép các tổ chức SSH (bạn có thể  cấu hình  bằng hướng dẫn  Cài đặt   Server  Ban đầu của  ta ). Trong bối cảnh của hướng dẫn này,  user  sudo trên mỗi  server  được đặt tên là sammy .
Ngoài ra, mỗi server trong số ba server đều có các yêu cầu cấu hình riêng:
- 
Trên web server : - Cài đặt và cấu hình web server Nginx. Để thực hiện việc này, hãy làm theo hướng dẫn của ta về Cách cài đặt Nginx trên Ubuntu 16.04 .
 
- 
Trên server ứng dụng : - Cài đặt Node.js bằng PPA chính thức, như được giải thích trong Cách cài đặt Node.js trên Ubuntu 16.04 . Một vài tính năng của Rails, chẳng hạn như Asset Pipeline, phụ thuộc vào JavaScript Runtime và Node.js cung cấp chức năng này.
- Cài đặt khuôn khổ Ruby on Rails. Để thực hiện việc này, hãy làm theo hướng dẫn của ta về Cách cài đặt Ruby on Rails với rbenv trên Ubuntu 16.04 . Khi bạn làm theo hướng dẫn này, hãy đảm bảo cài đặt version Ruby mới nhất, tại thời điểm viết bài này, là Ruby 2.5.1.
- Cài đặt PostgreSQL,  như trong  phần đầu tiên của hướng dẫn Cách sử dụng PostgreSQL với Ứng dụng Ruby on Rails của bạn trên Ubuntu 14.04 . Phần này cũng mô tả cách cài đặt libpq-dev, một gói khác cần thiết cho cài đặt ba cấp này.
- Triển khai ứng dụng Rails bằng Puma. Nếu bạn không có ứng dụng của riêng mình để triển khai, hãy làm theo hướng dẫn của  ta  về Cách triển khai ứng dụng Rails với Puma và Nginx để triển khai ứng dụng mẫu. Lưu ý  trong phần “Cài đặt rbenv-vars Plugin” của  yêu cầu  này, bạn phải đặt  user  database  và password  để phản ánh các giá trị bạn sử dụng khi cài đặt PostgreSQL trên  server  database  . Ngoài ra, bạn phải cho phép cổng 3000qua firewall để phần “Tạo Database Sản xuất” hoạt động. Cuối cùng, bạn không cần phải hoàn thành hai bước cuối cùng của hướng dẫn tiên quyết này, “Tạo Puma Upstart Script” và “Cài đặt và cấu hình Nginx”.
 
- 
Trên server database : - Cài đặt và cấu hình phần mềm database  PostgreSQL. Làm theo hướng dẫn của  ta  về Cách cài đặt và sử dụng PostgreSQL trên Ubuntu 16.04 để biết hướng dẫn về cách thực hiện việc này. Khi bạn làm theo hướng dẫn  yêu cầu  này, hãy tạo một  role  PostgreSQL cho ứng dụng Rails của bạn với quyền superusercũng như database có cùng tên với role PostgreSQL. Trong suốt hướng dẫn này, role và database PostgreSQL đều được gọi là sammy .
- Đặt password cho role PostgreSQL mới được tạo. Bỏ qua lệnh đầu tiên trong phần “ Tạo user database production ” của hướng dẫn Puma (mà bạn cũng đã sử dụng để cài đặt server ứng dụng ) và làm theo các lệnh còn lại trong phần đó để thay đổi password của user database . Lưu ý tên của role PostgreSQL và password bạn đặt cho server database phải giống với tên mà bạn đặt trên cài đặt PostgreSQL của server ứng dụng .
 
- Cài đặt và cấu hình phần mềm database  PostgreSQL. Làm theo hướng dẫn của  ta  về Cách cài đặt và sử dụng PostgreSQL trên Ubuntu 16.04 để biết hướng dẫn về cách thực hiện việc này. Khi bạn làm theo hướng dẫn  yêu cầu  này, hãy tạo một  role  PostgreSQL cho ứng dụng Rails của bạn với quyền 
Bước 1 - Tạo User cho Đường hầm SSH
Đường hầm SSH là các kết nối được mã hóa có thể gửi dữ liệu từ một cổng trên  server  này đến cổng trên  server  khác, làm cho nó giống như một chương trình lắng nghe trên  server  thứ hai đang chạy trên  server  đầu tiên. Có một  user  chuyên dụng cho các tunnel  SSH giúp cải thiện tính bảo mật cho  cài đặt  của bạn: nếu kẻ xâm nhập giành được quyền truy cập vào  user  sammy trên một trong các  server  của bạn, họ sẽ không thể truy cập các  server  khác trong  cài đặt  ba tầng. Tương tự như vậy, nếu kẻ xâm nhập có được quyền truy cập vào  user  đường hầm , họ sẽ không thể chỉnh sửa file  trong folder  ứng dụng Rails cũng như không thể sử dụng sudo .
Trên mỗi  server , hãy tạo thêm một đường hầm có tên  user . Chức năng duy nhất của  user  đường hầm là tạo tunnel  SSH để tạo điều kiện giao tiếp giữa các  server , vì vậy, không giống như sammy , không cấp các  quyền  sudo đường hầm . Ngoài ra,  user  đường hầm không nên có quyền ghi vào folder  ứng dụng Rails. Chạy lệnh sau trên mỗi  server  để thêm  user  đường hầm :
- sudo adduser tunnel
Trên web server , chuyển sang user đường hầm .
- sudo su tunnel
Với quyền là user đường hầm , hãy tạo một cặp SSH key :
- ssh-keygen
Lưu khóa ở vị trí mặc định và không tạo passphrase (password bảo vệ) cho các khóa, vì làm như vậy có thể làm phức tạp quá trình xác thực sau này khi bạn tạo tunnel SSH giữa các server .
Sau khi tạo cặp khóa, hãy quay lại user sammy :
- exit
Bây giờ chuyển sang server ứng dụng và thực hiện lại các lệnh tương tự:
- sudo su tunnel
- ssh-keygen
- exit
 Đến đây bạn  đã  cấu hình  tất cả  user  mà bạn  cần  cho phần còn lại của hướng dẫn. Net, bạn sẽ thực hiện một số thay đổi đối với file  /etc/hosts cho mỗi  user  đường hầm để hợp lý hóa quá trình tạo tunnel  SSH.
Bước 2 - Cấu hình file server lưu trữ
Trong suốt hướng dẫn này, có nhiều lần bạn phải tham khảo địa chỉ IP của  server  ứng dụng hoặc  server  cơ sở dữ liệu trong một lệnh. Thay vì phải nhớ và nhập các địa chỉ IP này mỗi lần, bạn có thể thêm IP riêng của  server  ứng dụng và  server  cơ sở dữ liệu vào file  /etc/hosts . Điều này sẽ cho phép bạn sử dụng tên của họ trong các lệnh tiếp theo thay cho địa chỉ của họ và sẽ giúp quá trình  cài đặt  tunnel  SSH trơn tru hơn nhiều.
Xin  lưu ý , để mọi thứ đơn giản, hướng dẫn này hướng dẫn bạn thêm cả địa chỉ IP riêng của  server  ứng dụng và  server  cơ sở dữ liệu vào file  /etc/hosts trên mỗi  server  trong số ba  server . Mặc dù về mặt kỹ thuật, không cần thiết phải thêm địa chỉ IP riêng của hosts ứng dụng hoặc  server  cơ sở dữ liệu vào file  hosts của riêng chúng, nhưng làm như vậy sẽ không gây ra  sự cố nào . Phương pháp được mô tả ở đây được chọn đơn giản vì nhanh chóng và thuận tiện.
Trước tiên, hãy tìm địa chỉ IP riêng của server ứng dụng và server cơ sở dữ liệu của bạn. Nếu bạn đang sử dụng DigitalOcean Server, hãy chuyển đến Control Panel của bạn và nhấp vào tên của các Server này. Trên bất kỳ trang nào dành riêng cho Server của họ, cả địa chỉ IP công cộng và riêng tư đều được hiển thị gần đầu trang.
Sau đó, trên mỗi  server , mở file  /etc/hosts bằng editor  yêu thích của bạn và nối các dòng sau:
- sudo nano /etc/hosts
. . .
app-server_private_ip app-server
database-server_private_ip database-server
Bằng cách thêm các dòng này vào file này trên mỗi server , bạn có thể sử dụng tên server ứng dụng và server cơ sở dữ liệu trong các lệnh thường yêu cầu bạn sử dụng địa chỉ IP của các server này. Bạn sẽ sử dụng chức năng này để cài đặt SSH key để mỗi user đường hầm của bạn có thể kết nối với các server khác của bạn.
Bước 3 - Cài đặt Đăng nhập SSH
 Đến đây bạn  đã có  user  đường hầm và file  /etc/hosts được cập nhật trên cả ba  server   của bạn , bạn đã sẵn sàng để bắt đầu tạo kết nối SSH giữa chúng.
Khi bạn thực hiện bước này, hãy nghĩ đến ba tầng giống như một kim tự tháp, với server database ở dưới cùng, server ứng dụng ở giữa và web server ở trên cùng. Server ứng dụng phải có thể kết nối với server database để truy cập dữ liệu cần thiết cho ứng dụng Rails và web server phải có thể kết nối với server ứng dụng để nó có thứ gì đó để trình bày với user .
Do đó, bạn chỉ cần thêm public key SSH của mỗi user đường hầm vào server “bên dưới” nó, nghĩa là bạn phải thêm public key của user đường hầm web server vào server ứng dụng và thêm public key của user đường hầm server ứng dụng vào server database . Điều này sẽ cho phép bạn cài đặt các tunnel SSH được mã hóa giữa các tầng và ngăn chặn bất kỳ kẻ nghe trộm nào trên mạng đọc lưu lượng đi qua giữa chúng.
Để bắt đầu quá trình này, hãy sao chép public key  của  user  đường hầm trên  web server  , đặt tại /home/tunnel/.ssh/id_rsa.pub , vào file  /home/tunnel/.ssh/authorized_keys trên  server  ứng dụng .
Trên web server , hiển thị public key của user đường hầm trong terminal bằng lệnh sau:
- sudo cat /home/tunnel/.ssh/id_rsa.pub
Chọn kết quả văn bản và sao chép nó vào clipboard thời của hệ thống.
SSH vào server ứng dụng trong một phiên terminal riêng biệt và chuyển sang user tunnel :
- sudo su tunnel
Nối khóa trong  clipboard   của hệ thống  vào file  authorized_keys quyền_ khóa trên  server  ứng dụng . Bạn có thể sử dụng lệnh sau  để thực hiện  trong một bước. Hãy nhớ thay thế tunnel_ssh_publickey_copied_from_web_server bằng public key  trong  clipboard   của hệ thống :
- echo "tunnel_ssh_publickey_copied_from_web-server" >> /home/tunnel/.ssh/authorized_keys
Sau đó, sửa đổi các điều khoản trên authorized_keys  file  để ngăn chặn truy cập trái phép vào nó:
- chmod 600 /home/tunnel/.ssh/authorized_keys
Sau đó quay lại user sammy :
- exit
Tiếp theo, hiển thị public key  của  user  đường hầm trên  server  ứng dụng - đặt tại /home/tunnel/.ssh/id_rsa.pub - và dán nó vào file  /home/tunnel/.ssh/authorized_keys trên  server  database  :
- sudo cat /home/tunnel/.ssh/id_rsa.pub
- sudo su tunnel
Vì bạn không tạo cặp SSH key  trên  server  database  , bạn sẽ phải tạo folder  /home/tunnel/.ssh và điều chỉnh quyền của nó:
- mkdir /home/tunnel/.ssh
- chmod 700 /home/tunnel/.ssh
Sau đó, thêm public key  của  server  ứng dụng vào file  authorized_keys quyền_key và điều chỉnh các quyền của nó:
- echo "tunnel_ssh_publickey_copied_from_app-server" >> /home/tunnel/.ssh/authorized_keys
- chmod 600 /home/tunnel/.ssh/authorized_keys
Sau đó quay lại user sammy :
- exit
Tiếp theo, kiểm tra kết nối đầu tiên bằng cách sử dụng SSH để kết nối với server ứng dụng từ server web của bạn với quyền là user đường hầm :
- sudo su tunnel
- ssh tunnel@app-server
Lần đầu tiên bạn kết nối từ web server đến server ứng dụng , bạn sẽ thấy một thông báo yêu cầu bạn xác nhận máy bạn đang kết nối có thể tin cậy được. Nhập “yes” để chấp nhận tính xác thực của server ứng dụng :
The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
Bạn sẽ thấy biểu ngữ chào mừng từ server ứng dụng và dấu nhắc lệnh sẽ hiển thị rằng bạn đã đăng nhập vào server ứng dụng . Điều này xác nhận kết nối SSH từ web server đến server ứng dụng đang hoạt động bình thường.
Thoát khỏi kết nối SSH với server ứng dụng , sau đó thoát khỏi user đường hầm để quay lại user sammy của web server của bạn:
- exit
- exit
Tiếp theo, hãy làm theo các bước tương tự sau để kiểm tra kết nối SSH từ server ứng dụng đến server cơ sở dữ liệu :
- sudo su tunnel
- ssh tunnel@database-server
Chấp nhận tính xác thực của server database . Khi bạn nhìn thấy biểu ngữ chào mừng và dấu nhắc lệnh từ server database , bạn sẽ biết rằng kết nối SSH từ server ứng dụng đến server cơ sở dữ liệu đang hoạt động như mong đợi.
Thoát khỏi kết nối SSH đến server database , sau đó thoát khỏi user đường hầm :
- exit
- exit
Các kết nối SSH mà bạn đã cài đặt ở bước này tạo thành cơ sở của các tunnel SSH sẽ cho phép truyền thông an toàn giữa ba cấp server của bạn. Tuy nhiên, ở dạng hiện tại, những kết nối này dễ bị hỏng và do đó chúng không tin cậy như chúng có thể. Tuy nhiên, bằng cách cài đặt một số phần mềm bổ sung và cấu hình tunnel hoạt động như một dịch vụ, bạn có thể giảm thiểu những lỗ hổng này.
Bước 4 - Cài đặt Đường hầm SSH liên tục đến Server database
Trong bước cuối cùng, bạn đã truy cập dấu nhắc lệnh trên server từ xa từ server local . Đường hầm SSH cho phép bạn làm được nhiều hơn thế bằng cách tạo tunnel lưu lượng truy cập từ các cổng trên server local đến các cổng trên server từ xa. Tại đây, bạn sẽ sử dụng một tunnel SSH để mã hóa kết nối giữa server ứng dụng và server cơ sở dữ liệu .
Nếu bạn đã làm theo tất cả các  yêu cầu  cho hướng dẫn này, bạn sẽ cài đặt được PostgreSQL trên cả  server  ứng dụng và  server  cơ sở dữ liệu . Để tránh xung đột về số cổng, bạn phải  cấu hình  tunnel  SSH giữa các  server  này để chuyển tiếp kết nối từ cổng 5433 của  server  ứng dụng đến cổng 5432 trên  server  database  . Sau đó, bạn sẽ  cấu hình  lại ứng dụng Rails  của bạn  (được lưu trữ trên  server  ứng dụng của bạn) để sử dụng version  PostgreSQL đang chạy trên  server  database  .
Bắt đầu với quyền là user sammy trên server ứng dụng , hãy chuyển sang user đường hầm mà bạn đã tạo ở Bước 1:
- sudo su tunnel
Chạy lệnh ssh với các cờ và tùy chọn sau để tạo tunnel  giữa  server  ứng dụng và  server  cơ sở dữ liệu :
- ssh -f -N -L 5433:localhost:5432 tunnel@database-server
- Tùy chọn -fgửisshxuống nền. Điều này cho phép bạn chạy các lệnh mới trong dấu nhắc hiện có của bạn trong khi tunnel tiếp tục chạy như một quá trình .
- Tùy chọn -Nchosshkhông thực hiện lệnh từ xa. Điều này được sử dụng ở đây vì bạn chỉ muốn chuyển tiếp các cổng.
- Tùy chọn -Lđược theo sau bởi giá trị cấu hình5433:localhost:5432. Điều này chỉ định rằng lưu lượng truy cập từ cổng5433ở phía local ( server ứng dụng ) được chuyển tiếp đến cổng5432của localhost trên server từ xa ( server cơ sở dữ liệu ). Lưu ý localhost ở đây là từ quan điểm của server từ xa.
- Phần cuối cùng của lệnh, tunnel@database-server, chỉ định user và server từ xa để kết nối.
Sau khi cài đặt tunnel SSH, quay lại user sammy :
- exit
Đến đây, tunnel đang chạy, nhưng không có gì theo dõi đảm bảo rằng nó vẫn hoạt động. Nếu quá trình gặp sự cố, tunnel sẽ đi xuống, ứng dụng Rails sẽ không thể giao tiếp với database của nó nữa và bạn sẽ bắt đầu thấy lỗi.
Hãy giết tunnel mà bạn đã tạo bây giờ vì ta sẽ cài đặt tin cậy hơn. Vì kết nối ở chế độ nền, bạn sẽ phải tìm ID tiến trình của nó để loại bỏ nó. Bởi vì mọi tunnel được tạo bởi user đường hầm , bạn có thể tìm thấy ID tiến trình của nó bằng cách liệt kê các quy trình hiện tại và lọc kết quả cho từ khóa 'đường hầm':
- ps axu | grep tunnel
Kết quả sẽ trả về một cái gì đó giống như kết quả bên dưới:
tunnel   21814  0.0  0.1  44920   692 ?        Ss   14:12   0:00 ssh -f -N -L 5433:localhost:5432 tunnel@database-server
sammy    21816  0.0  0.2  12916  1092 pts/0    S+   14:12   0:00 grep --color=auto tunnel
Dừng quá trình bằng cách chạy lệnh kill theo sau là ID tiến trình của nó:
- sudo kill 21814
Để duy trì kết nối SSH liên tục giữa  server  ứng dụng và database , hãy cài đặt autossh . autossh là một chương trình khởi động và giám sát kết nối SSH và khởi động lại nó nếu kết nối chết hoặc ngừng truyền lưu lượng:
- sudo apt-get install autossh
systemd là hệ thống init mặc định trên Ubuntu ,  nghĩa là  nó quản lý các tiến trình sau khi hệ thống khởi động. Bạn có thể sử dụng systemd để tạo một dịch vụ sẽ quản lý và tự động khởi động tunnel  SSH của bạn khi  server  khởi động lại. Để thực hiện việc này, hãy tạo một file  có tên db-tunnel.service trong folder  /lib/systemd/system/ , vị trí tiêu chuẩn nơi các file  đơn vị systemd được lưu trữ:
- sudo nano /lib/systemd/system/db-tunnel.service
Thêm nội dung sau vào file  mới để  cấu hình  dịch vụ cho systemd quản lý:
[Unit]
Wants=network-online.target
After=network-online.target
[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 5433:localhost:5432 tunnel@database-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process
[Install]
WantedBy=multi-user.target
Dòng quan trọng ở đây là ExecStart . Điều này chỉ định đường dẫn đầy đủ đến lệnh và các đối số mà nó cần thực thi để bắt đầu quá trình. Tại đây, nó bắt đầu một bash shell mới và sau đó chạy chương trình autossh .
 Lưu file  , sau đó  reload  cấu hình systemd  đảm bảo  rằng nó chọn file  dịch vụ mới:
- sudo systemctl daemon-reload
Bật dịch vụ db-tunnel để tunnel  tới  server  database  tự động khởi động  khi  nào  server  khởi động:
- sudo systemctl enable db-tunnel.service
Sau đó, bắt đầu dịch vụ:
- sudo systemctl start db-tunnel.service
Chạy lại lệnh sau để kiểm tra xem tunnel có lên không:
- ps axu | grep tunnel
Trong  kết quả , bạn sẽ thấy rằng có nhiều quy trình hơn đang chạy trong thời gian này vì autossh hiện đang giám sát tunnel :
tunnel   25925  0.0  0.1   4376   704 ?        Ss   14:45   0:00 /usr/lib/autossh/autossh -N -L 5432:localhost:5432 tunnel@database-server
tunnel   25939  0.2  1.0  44920  5332 ?        S    14:45   0:00 /usr/bin/ssh -L 61371:127.0.0.1:61371 -R 61371:127.0.0.1:61372 -N -L 5432:localhost:5432 tunnel@database-server
sammy    25941  0.0  0.2  12916  1020 pts/0    S+   14:45   0:00 grep --color=auto tunnel
Bây giờ tunnel  đã được  cài đặt  và chạy, bạn có thể kiểm tra kết nối với  server  database  bằng psql  đảm bảo  rằng nó đang hoạt động chính xác.
Khởi động client  psql và yêu cầu nó kết nối với localhost . Bạn cũng phải chỉ định cổng 5433 để kết nối qua tunnel  SSH với cá thể PostgreSQL trên  server  database  . Chỉ định tên database  bạn đã tạo trước đó và nhập password  bạn đã tạo cho  user  database  khi  được yêu cầu :
- psql -hlocalhost -p5433 sammy
Nếu bạn thấy thứ gì đó giống như kết quả sau, kết nối database đã được cài đặt chính xác:
psql (9.5.10)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
sammy=#
Để đóng  dấu nhắc  PostgreSQL, hãy nhập \q rồi nhấn ENTER .
Cuối cùng, bạn có một tunnel SSH liên tục, tin cậy để mã hóa lưu lượng giữa server ứng dụng và server cơ sở dữ liệu . Các tính năng bảo mật của tunnel là key quan trọng, bởi vì chính tunnel này mà ứng dụng Rails trên server ứng dụng của bạn sẽ giao tiếp với version PostgreSQL trên server database của bạn.
Bước 5 - Cấu hình Rails để sử dụng database từ xa
Bây giờ tunnel từ server ứng dụng đến server cơ sở dữ liệu đã được cài đặt , bạn có thể sử dụng nó như một kênh bảo mật để ứng dụng Rails của bạn kết nối qua tunnel với version PostgreSQL trên server database .
Mở file cấu hình database của ứng dụng:
- nano /home/sammy/appname/config/database.yml
Cập nhật phần production để số cổng được chỉ định làm biến môi trường. Bây giờ nó sẽ trông giống như sau:
. . .
production:
  <<: *default
  host: localhost
  adapter: postgresql
  encoding: utf8
  database: appname_production
  pool: 5
  username: <%= ENV['APPNAME_DATABASE_USER'] %>
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
  port: <%= ENV['APPNAME_DATABASE_PORT'] %>
 Lưu file   này, sau đó mở .rbenv-vars trong folder  ứng dụng và chỉnh sửa các biến môi trường:
- nano /home/sammy/appname/.rbenv-vars
Nếu bạn đặt tên và password  khác cho  role  PostgreSQL trên  server  database  , hãy thay thế chúng ngay bây giờ (trong ví dụ bên dưới,  role  PostgreSQL được đặt tên là sammy ). Ngoài ra, hãy thêm một dòng mới để chỉ định cổng database . Sau khi thực hiện những thay đổi này, .rbenv-vars của bạn sẽ trông giống như sau:
SECRET_KEY_BASE=secret_key_base
APPNAME_DATABASE_USER=sammy
APPNAME_DATABASE_PASSWORD=database_password
APPNAME_DATABASE_PORT=5433
Lưu file này khi hoàn tất.
Vì bạn hiện đang sử dụng version PostgreSQL trên server database thay vì version trên server ứng dụng nơi bạn triển khai ứng dụng Rails của bạn , bạn sẽ phải cài đặt lại database .
Trên  server  ứng dụng ,  chuyển  đến folder  ứng dụng của bạn và chạy lệnh rake để  cài đặt  database :
Lưu ý: Lệnh này sẽ không di chuyển bất kỳ dữ liệu nào từ database  hiện có sang database  mới. Nếu bạn đã có dữ liệu quan trọng trên database   của bạn , bạn nên  backup  dữ liệu đó rồi khôi phục lại sau.
- cd /home/sammy/appname
- rake db:setup
Khi lệnh này hoàn tất, ứng dụng Rails của bạn sẽ bắt đầu giao tiếp với version  PostgreSQL trên  server  database  qua một tunnel  SSH được mã hóa. Điều tiếp theo cần làm là cấu hình Puma như một dịch vụ systemd để quản lý dễ dàng hơn.
Bước 6 - Cấu hình và khởi động Puma
Tương tự như cách bạn  cài đặt  dịch vụ db-tunnel ở Bước 4, bạn sẽ  cấu hình  systemd để chạy Puma (phần mềm  server  bạn đã cài đặt trên  server  ứng dụng như một phần của  yêu cầu ) như một dịch vụ. Chạy Puma như một dịch vụ cho phép nó tự động khởi động khi  server  khởi động hoặc tự động khởi động lại nếu nó gặp sự cố, giúp việc triển khai của bạn mạnh mẽ hơn.
Tạo một file  mới có tên puma.service trong folder  /lib/systemd/system/ :
- sudo nano /lib/systemd/system/puma.service
Thêm nội dung sau, được điều chỉnh từ tài liệu systemd của Puma , vào file  mới. Đảm bảo cập nhật các giá trị được đánh dấu trong chỉ thị User , WorkingDirectory và ExecStart để phản ánh cấu hình  của bạn :
[Unit]
Description=Puma HTTP Server
After=network.target
[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple
# Preferably configure a non-privileged user
User=sammy
# The path to the puma application root
# Also replace the "<WD>" place holders below with this path.
WorkingDirectory=/home/sammy/appname
# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1
Environment=RAILS_ENV=production
# The command to start Puma.
ExecStart=/home/sammy/.rbenv/bin/rbenv exec bundle exec puma -b tcp://127.0.0.1:9292
Restart=always
[Install]
WantedBy=multi-user.target
Lưu và đóng  file . Sau đó  reload  systemd , kích hoạt dịch vụ Puma và khởi động Puma:
- sudo systemctl daemon-reload
- sudo systemctl enable puma.service
- sudo systemctl start puma.service
Sau đó, xác nhận Puma đang chạy bằng cách kiểm tra trạng thái của dịch vụ:
- sudo systemctl status puma.service
Nếu nó đang chạy, bạn sẽ thấy một kết quả tương tự như sau:
puma.service - Puma HTTP Server
   Loaded: loaded (/lib/systemd/system/puma.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2017-12-26 05:35:50 UTC; 1s ago
 Main PID: 15051 (bundle)
    Tasks: 2
   Memory: 31.4M
      CPU: 1.685s
   CGroup: /system.slice/puma.service
           └─15051 puma 3.11.0 (tcp://127.0.0.1:9292) [appname]
Dec 26 05:35:50 app systemd[1]: Stopped Puma HTTP Server.
Dec 26 05:35:50 app systemd[1]: Started Puma HTTP Server.
Dec 26 05:35:51 app rbenv[15051]: Puma starting in single mode...
Dec 26 05:35:51 app rbenv[15051]: * Version 3.11.0 (ruby 2.4.3-p205), codename: Love Song
Dec 26 05:35:51 app rbenv[15051]: * Min threads: 5, max threads: 5
Dec 26 05:35:51 app rbenv[15051]: * Environment: production
Tiếp theo, sử dụng curl để truy cập và in nội dung của trang web để bạn có thể kiểm tra xem nó có được cung cấp chính xác hay không. Lệnh sau yêu cầu curl truy cập  server  Puma mà bạn vừa khởi động trên  server  ứng dụng trên cổng 9292 :
- curl localhost:9292/tasks
Nếu bạn thấy mã nào đó giống như mã bên dưới, thì nó xác nhận cả Puma và kết nối database đang hoạt động chính xác:
...
<h1>Tasks</h1>
<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Note</th>
      <th colspan="3"></th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>
...
Khi bạn có thể xác nhận ứng dụng Rails của bạn đang được Puma phân phát và được cấu hình chính xác để sử dụng version PostgreSQL từ xa trên server database , bạn có thể chuyển sang cài đặt tunnel SSH giữa web server và server ứng dụng .
Bước 7 - Cài đặt và duy trì Đường hầm SSH với Server ứng dụng
Bây giờ server ứng dụng đã được cài đặt và đang chạy, bạn có thể kết nối nó với web server . Tương tự như quy trình bạn đã trải qua ở Bước 4, bạn sẽ thực hiện việc này bằng cách cài đặt một tunnel SSH khác. Đường hầm này sẽ cho phép Nginx trên web server kết nối an toàn qua kết nối được mã hóa với Puma trên server ứng dụng .
Bắt đầu bằng cách cài đặt autossh trên  web server  :
- sudo apt-get install autossh
Tạo một file  mới có tên app-tunnel.service trong folder  /lib/systemd/system/ :
- sudo nano /lib/systemd/system/app-tunnel.service
Thêm nội dung sau vào file  này.   , dòng quan trọng là dòng bắt đầu với ExecStart . Ở đây, dòng này chuyển tiếp cổng 9292 trên  web server  đến cổng 9292 trên  server  ứng dụng nơi Puma đang nghe:
[Unit]
StopWhenUnneeded=true
Wants=network-online.target
After=network-online.target
[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 9292:localhost:9292 tunnel@app-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process
[Install]
WantedBy=multi-user.target
Lưu ý: Số cổng trong dòng ExecStart giống với số cổng được  cấu hình  cho Puma ở bước trước.
 Reload  systemd để nó đọc file  dịch vụ mới, sau đó bật và khởi động dịch vụ app-tunnel :
- sudo systemctl daemon-reload
- sudo systemctl enable app-tunnel.service
- sudo systemctl start app-tunnel.service
Kiểm tra xem tunnel đã lên chưa:
- ps axu | grep tunnel
Bạn sẽ thấy một cái gì đó giống như kết quả bên dưới:
tunnel   19469  0.0  0.1   4376   752 ?        Ss   05:45   0:00 /usr/lib/autossh/autossh -N -L 9292:localhost:9292 tunnel@app-server
tunnel   19482  0.5  1.1  44920  5568 ?        S    05:45   0:00 /usr/bin/ssh -L 54907:127.0.0.1:54907 -R 54907:127.0.0.1:54908 -N -L 9292:localhost:9292 tunnel@app-server
sammy    19484  0.0  0.1  12916   932 pts/0    S+   05:45   0:00 grep --color=auto tunnel
 Danh sách tiến trình  được lọc này cho thấy rằng autossh đang chạy và nó đã bắt đầu một quy trình ssh khác tạo tunnel  được mã hóa thực tế giữa  web server  và  server  ứng dụng .
Đường hầm thứ hai của bạn hiện đã được cài đặt và mã hóa giao tiếp giữa web server và server ứng dụng của bạn . Tất cả những gì còn lại bạn phải làm để cài đặt và chạy ứng dụng Rails ba tầng của bạn là cấu hình Nginx để chuyển các yêu cầu đến Puma.
Bước 8 - Cấu hình Nginx
Đến đây, tất cả các kết nối và tunnel SSH cần thiết đã được cài đặt và mỗi trong ba tầng server của bạn có thể giao tiếp với nhau. Phần cuối cùng của câu đố này là bạn phải cấu hình Nginx để gửi yêu cầu đến Puma để cài đặt hoạt động đầy đủ.
Trên  web server  , tạo file  cấu hình Nginx mới tại /etc/nginx/sites-available/ appname :
- sudo nano /etc/nginx/sites-available/appname
Thêm nội dung sau vào file . Tệp cấu hình Nginx này tương tự như file  bạn đã sử dụng nếu bạn làm theo hướng dẫn của  ta  về Cách triển khai ứng dụng Rails với Puma và Nginx . Sự khác biệt chính là vị trí của ứng dụng ngược dòng; thay vì sử dụng file   socket  local , cấu hình này trỏ Nginx đến tunnel  SSH đang nghe trên cổng 9292 :
upstream app {
    server 127.0.0.1:9292;
}
server {
    listen 80;
    server_name localhost;
    root /home/sammy/appname/public;
    try_files $uri/index.html $uri @app;
    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }
    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}
Lưu file này, sau đó kích hoạt trang web và áp dụng các thay đổi .
Trước tiên, hãy xóa trang web mặc định:
- sudo rm /etc/nginx/sites-enabled/default
Thay đổi thành folder  sites-enabled Nginx:
- cd /etc/nginx/sites-enabled
Tạo một  softlink  trong folder  sites-enabled đến file  bạn vừa tạo ngay bây giờ trong folder  sites-available :
- sudo ln -s /etc/nginx/sites-available/appname appname
Kiểm tra cấu hình Nginx của bạn để tìm lỗi cú pháp:
- sudo nginx -t
Nếu có lỗi , hãy quay lại và kiểm tra file của bạn trước khi tiếp tục.
Khi đã sẵn sàng , hãy khởi động lại Nginx để nó đọc cấu hình mới của bạn:
- sudo systemctl restart nginx
Nếu bạn đã làm theo hướng dẫn Puma trong yêu cầu , bạn sẽ cài đặt Nginx và PostgreSQL trên server ứng dụng . Cả hai đều được thay thế bằng các version riêng biệt chạy trên hai server khác, vì vậy các chương trình này là dư thừa. Do đó, bạn nên xóa các gói này khỏi server ứng dụng :
- sudo apt remove nginx
- sudo apt remove postgresql
Sau khi loại bỏ các gói này, hãy nhớ cập nhật các luật firewall của bạn để ngăn chặn bất kỳ lưu lượng truy cập không mong muốn nào truy cập vào các cổng này.
Ứng dụng Rails của bạn hiện đã được production . Truy cập IP công cộng của web server của bạn trong trình duyệt web để xem nó hoạt động:
http://web-server_public_IP/tasks
Kết luận
Theo hướng dẫn này, bạn đã triển khai ứng dụng Rails của bạn trên kiến trúc ba tầng và bảo mật các kết nối từ web server của bạn đến server ứng dụng và từ server ứng dụng đến server cơ sở dữ liệu bằng các tunnel SSH được mã hóa.
Với các thành phần khác nhau của ứng dụng của bạn trên các server riêng biệt, bạn có thể chọn các thông số kỹ thuật tối ưu cho từng server dựa trên lượng lưu lượng truy cập mà trang web nhận được. Bước đầu tiên để thực hiện việc này là theo dõi tài nguyên mà server đang sử dụng. Xem hướng dẫn của ta về giám sát CPU để biết hướng dẫn về cách giám sát việc sử dụng CPU của server của bạn. Nếu bạn thấy rằng mức sử dụng CPU hoặc bộ nhớ trên một tầng là rất cao, bạn có thể thay đổi kích thước server trên một cấp đó. Để được tư vấn thêm về việc chọn kích thước server , hãy xem hướng dẫn của ta về Chọn server phù hợp cho ứng dụng của bạn .
Bước tiếp theo ngay lập tức, bạn cũng nên bảo mật kết nối từ user của bạn đến web server bằng cách cài đặt certificate SSL trên web server . Hãy xem hướng dẫn Nginx Let's Encrypt để biết hướng dẫn. Ngoài ra, nếu bạn muốn tìm hiểu thêm về cách sử dụng tunnel SSH, hãy xem hướng dẫn này .
Các tin liên quan
 

