Cách vận hành máy chủ MongoDB an toàn với OpenVPN và Docker trên Ubuntu 16.04

1 năm trước

 

MongoDB là một cơ sở dữ liệu NoSQL nguồn mở. Một thiết lập MongoDB truyền thống thiếu một số tính năng bảo mật mà bạn muốn nếu như bạn lo ngại về vấn đề bảo mật dữ liệu.

Có một vài phương pháp để bảo mật máy chủ chạy cơ sở dữ liệu. Trước tiên, có thể thiết lập VPN và hạn chế quyền truy cập với chỉ những khách hàng được kết nối với VPN. Sau đó, có thể mã hóa lớp truyền tải giữa máy khách và máy chủ với các chứng chỉ. Bạn sẽ làm cả hai trong hướng dẫn này. Ngoài ra, bạn sẽ sử dụng Docker để chạy phiên bản MongoDB của bạn, vì vậy có thể đảm bảo khả năng sử dụng lại cấu hình và chứng chỉ MongoDB trên nhiều máy chủ.

 

Điều kiện tiên quyết

Để hoàn thành hướng dẫn này, bạn cần

  • Máy chủ OpenVPN mà bạn có thể thiết lập bằng cách làm theo hướng dẫn thiết lập máy chủ OpenVPN trên Ubuntu 16.04. Đảm bảo bạn chọn hộp Private networking khi tạo máy chủ.
  • Máy tính Ubuntu 16.04 với Docker được cài đặt. Đây là nơi tạo ra hình ảnh DockoDB Docker, và là nơi chạy MongoDB trong container. Bật private networking trên máy chủ của bạn.
  • Một người dùng non-root với quyền sudo trên cả hai máy chủ. Hướng dẫn cài đặt ban đầu cho Ubuntu 16.04 sẽ giải thích cách thiết lập.
  • MongoDB được cài đặt trên máy cục bộ của bạn. Bạn sẽ sử dụng nó để kiểm tra kết nối đến máy chủ MongoDB.
 

Bước 1 - Cấu hình VPN để chuyển tiếp đến địa chỉ Private IP.

Nếu bạn theo dõi bài viết về OpenVPN trước đây, bạn có thể cấu hình máy chủ để chuyển tiếp các yêu cầu tới giao diện mạng công cộng, nhưng không phải là yêu cầu riêng tư. Trong hướng dẫn này, chúng ta sẽ cấu hình máy chủ MongoDB để nó chỉ có thể được truy cập trên giao diện riêng của nó, mà chỉ có thể truy cập thông qua kết nối VPN của chúng ta. Cần sửa đổi các quy tắc IP fowarding trên máy chủ VPN để traffic từ các máy khách VPN cũng được định tuyến đến mạng riêng.

Kết nối với máy chủ OpenVPN.

ssh sammy@vpn_server_public_ip

Sau đó chọn VPN Droplet của bạn và tìm địa chỉ private IP của.

Khi có địa chỉ private IP, hãy thực hiện lệnh này trên VPN Droplet để xác định giao diện mạng sử dụng địa chỉ IP đó:

vpn-serversudo nano /etc/ufw/before.rules
vpn-server ip route | grep vpn_server_private_ip

Bạn sẽ thấy kết quả giống như sau:

Output 10.132.0.0/16 dev eth1 proto kernel scope link src vpn_server_private_ip
 

Lưu ý giao diện mạng trong kết quả của bạn. Trong ví dụ này, giao diện là eth1, nhưng giao diện của bạn có thể khác.

Khi bạn đã xác định được giao diện mạng private, hãy chỉnh sửa tệp /etc/ufw/before.rules:

vpn-server sudo nano /etc/ufw/before.rules
  •  

Xác định vị trí công đoạn bạn đã xác định trong hướng dẫn điều kiện tiên quyết, trông giống như sau:

/etc/ufw/before.rules
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES

Thêm quy tắc mới cho giao diện mạng riêng:

/etc/ufw/before.rules
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE-A POSTROUTING -s 10.8.0.0/8 -o eth1 -j MASQUERADECOMMIT
# END OPENVPN RULES

Hãy chắc chắn thay thế eth1 bằng giao diện mạng riêng của bạn. Sau đó lưu tệp và thoát khỏi trình chỉnh sửa.

Tắt và bật lại tường lửa:

vpn-server sudo ufw disable 
vpn-server sudo ufw enable
  •  

Sau đó đăng xuất khỏi máy chủ VPN của bạn.

vpn-server exit
  •  

Bây giờ hãy thiết lập kết nối VPN từ máy tính cục bộ của bạn đến máy chủ VPN. Duy trì kết nối trong suốt hướng dẫn này.

Bây giờ hãy kết nối với máy chủ MongoDB bằng địa chỉ private IP và cấu hình tường lửa.

 

Bước 2 - Thiết lập tường lửa của máy chủ MongoDB

Chúng ta sẽ kết nối với máy chủ MongoDB bằng địa chỉ private IP. Nếu bạn không có, hãy tìm địa chỉ private IP cho MongoDB Docker Droplet. Bạn sẽ sử dụng nó để kết nối với máy chủ, và sau đó sử dụng nó để kết nối trực tiếp với MongoDB, vì chúng ta sắp giới hạn quyền truy cập vào máy chủ cơ sở dữ liệu cho các máy khách VPN. Bằng cách này sẽ tránh làm lộ cơ sở dữ liệu công khai, đây là một biện pháp bảo mật phải có.

Đảm bảo bạn đã kết nối với VPN của bạn và SSH đến máy chủ MongoDB bằng địa chỉ private IP:

ssh sammy@mongodb_server_private_ip

Khi đã đăng nhập, hãy xóa tất cả các quy tắc tường lửa hiện có để ngăn truy cập từ thế giới bên ngoài:

mongo-server sudo ufw delete limit ssh 
mong-server sudo ufw delete allow 2375/tcp 
mongo-server sudo ufw delete allow 2376/tcp

Sau đó, thêm hai quy tắc mới cho phép truy cập SSH và MongoDB chỉ từ các máy tính được kết nối với VPN của bạn. Để thực hiện điều đó, hãy sử dụng địa chỉ private IP của máy chủ VPN cho IP gốc:

mongo-server sudo ufw allow from vpn_server_private_ip to any port 22 proto tcp
mongo-server sudo ufw allow from vpn_server_private_ip to any port 28018 proto tcp 

 

Đảm bảo đây là hai quy tắc được định cấu hình duy nhất:

mongo-server sudo ufw status
  •  

Bạn sẽ thấy kết quả sau:

Output 
To Action From 
-- ------ ----
22/tcp ALLOW vpn_server_private_ip 
28018/tcp ALLOW vpn_server_private_ip
 

Bật tường lửa và đăng xuất khỏi máy chủ:

mongo-server sudo ufw enable 
mongo-server exit
  •  

Sau đó đăng nhập lại vào máy chủ MongoDB để đảm bảo bạn vẫn có quyền truy cập vào máy chủ sau khi bật bộ lọc IP.

ssh sammy@mongodb_server_private_ip

Nếu bạn không thể thiết lập kết nối SSH, hãy đảm bảo bạn đã kết nối với VPN và thiết lập máy chủ VPN để chuyển tiếp traffic truy cập trên mạng riêng. Nếu điều đó không hiệu quả, hãy kiểm tra các quy tắc tường lửa. Đảm bảo bạn đã chỉ định private IP của máy chủ VPN trong các quy tắc chứ không phải private IP của máy chủ MongoDB.

Để tìm hiểu thêm về UFW, khám phá hướng dẫn UFW trên Ubuntu.

Bây giờ bạn đã tinh chỉnh các biện pháp bảo mật cơ bản, hãy tiến hành cấu hình MongoDB.

 

Bước 3 - Tạo tệp cấu hình MongoDB

Trong bước này, chúng ta sẽ tạo một cấu hình MongoDB tùy chỉnh để cấu hình nên MongoDB sử dụng các chứng chỉ SSL.

Hãy tạo một cấu trúc thư mục để giữ cấu hình và các tệp liên quan. Tạo một thư mục có tên là mongoconf, và sau đó tạo một thư mục config bên trong thư mục đó cho các tệp cấu hình khác. Trong thư mục config, tạo một thư mục có tên là ssl, nơi lưu trữ các chứng chỉ.

Tạo cấu trúc bằng lệnh sau:

mongo-server mkdir -p ~/mongoconf/config/ssl

Sau đó chuyển sang thư mục ~/mongoconf/config:

mongo-server cd ~/mongoconf/config

Mở một tệp mới có tên là mongod.conf bằng trình soạn thảo văn bản:

mongo-server nano mongod.conf
  •  

Đầu tiên, thiết lập cơ sở dữ liệu để liên kết với mọi giao diện mạng trên cổng 28018. Sự liên kết với 0.0.0.0 không phải là vấn đề bảo mật trong trường hợp này vì tường lửa sẽ không cho phép kết nối từ thế giới bên ngoài. Nhưng chúng ta cần phải cho phép kết nối từ các client bên trong VPN. Thêm phần sau vào tệp:

mongodb.conf
net: 
bindIp: 0.0.0.0 
port: 28018

Cũng trong công đoạn net, đặt đường dẫn đến chứng chỉ SSL và chỉ định cụm mật khẩu chứng chỉ. Chúng tôi sẽ sớm tạo các tệp chứng thực thực tế và cụm mật khẩu.

mongodb.conf
net: 
. . .
ssl: 
CAFile: /etc/mongo/ssl/client.pem
PEMKeyFile: /etc/mongo/ssl/server.pem
PEMKeyPassword: test
mode: requireSSL

Cuối cùng, đặt thư mục lưu trữ mặc định và bật nhật ký.

mongodb.conf
. . .
storage: 
dbPath: /mongo/db
journal: 
enabled: true

Để tìm hiểu về tất cả các tùy chọn cấu hình có sẵn, hãy đọc tài liệu của MongoDB.

Bây giờ, lưu tệp và thoát khỏi trình chỉnh sửa. Đã đến lúc tạo chứng chỉ SSL mà chúng ta sẽ sử dụng.

 

Bước 4 - Tạo chứng chỉ SSL

Để bảo mật việc truyền dữ liệu, cần tạo hai chứng chỉ SSL cho MongoDB - một cho máy chủ và một cho client sẽ truy cập cơ sở dữ liệu.

Lưu ý: Chúng tôi tạo chứng chỉ self-signed trong hướng dẫn này. Trong môi trường sản xuất, hãy sử dụng cơ quan cấp tín chỉ đáng tin cậy để tạo chúng.

Để thực hiện điều này, cần thiết lập trình phân giải private DNS. Sau đó, sử dụng thử thách Mã hóa DNS để xác thực các tên miền mạng nội bộ mới được tạo và cấp chứng chỉ cho chúng.

Đầu tiên, hãy thay đổi thư mục ~/mongoconf/config/ssl và tạo cặp khóa chứng chỉ máy chủ. Điền vào các dấu nhắc với thông tin bạn chọn. Chú ý Common Name và PEM Passphrase.

mongo-server cd ~/mongoconf/config/ssl 
mongo-server openssl req -new -x509 -days 365 -out server.crt -keyout server.key

 

Bạn sẽ thấy kết quả sau và sẽ được yêu cầu cung cấp một số chi tiết trong quá trình thực hiện:

Server certificate-key generation . . .
Enter PEM pass phrase: test 
Verifying - Enter PEM pass phrase: test . . . 
 Common Name (e.g. server FQDN or YOUR name) []: mongodb_server_private_ip 
 . . .
 

Khi bạn được yêu cầu nhập cụm từ PEM, hãy đảm bảo sử dụng cùng một giá trị bạn đã sử dụng trong tệp cấu hình MongoDB của mình trong bước trước.

MongoDB không chấp nhận các tệp chứng chỉ và khóa riêng biệt, vì vậy hãy kết hợp chúng thành một tệp .pem đơn:

mongo-server cat server.crt server.key >> server.pem

Tiếp theo, tạo cặp khóa chứng chỉ cho client:

mongo-server openssl req -new -x509 -days 365 -out client.crt -keyout client.key

Bạn sẽ làm theo cùng một quy trình như trước, nhưng lần này sử dụng private IP của máy chủ VPN. Cụm từ thông qua PEM có thể là bất cứ điều gì bạn muốn cho bước này.

Client certificate-key generation. . . 
Enter PEM pass phrase: secret_password Verifying - Enter PEM pass phrase:secret_password. . .
Common Name (e.g. server FQDN or YOUR name) []: vpn_server_private_ip. . .
 

Nối các tệp bạn vừa tạo vào một tệp .pem đơn

mongo-server cat client.crt client.key >> client.pem

Tiếp theo, sao chép cả hai tệp chứng chỉ vào máy cục bộ của bạn để có thể kết nối với máy chủ MongoDB từ xa. Có thể làm điều này với lệnh scp trên máy cục bộ của bạn:

mongo-server scp sammy@mongodb_server_private_ip:/home/sammy/mongoconf/config/ssl/\{client.pem,server.pem\}.

Ngoài ra, bạn có thể làm theo hướng dẫn sử dụng SFTP với Serverto từ xa để chuyển an toàn các tập tin client.pem và server.pem vào máy cục bộ của bạn.

Bây giờ hãy tạo hình ảnh Docker và chạy công cụ cơ sở dữ liệu trong container để cấu hình này có thể di động hơn.

 

Bước 5 - Tạo hình ảnh MongoDB Docker và vận hành Container

Bạn đã tạo cấu hình MongoDB an toàn và tạo các chứng chỉ. Bây giờ chúng ta hãy làm cho nó di động với Docker. Chúng ta sẽ tạo một hình ảnh tùy chỉnh cho MongoDB, nhưng sẽ chuyển qua tệp cấu hình và chứng chỉ khi vận hành container.

Để tạo hình ảnh, bạn cần một Dockerfile.

Lưu ý: Để chạy docker mà không có sudo, thêm sammy vào nhóm docker: mongo-server sudo usermod -aG docker sammy 

Sau đó đăng xuất khỏi máy chủ và đăng nhập lại để các quyền của nhóm mới có hiệu lực.

Chuyển sang thư mục root của project và mở một Dockerfile trống trong trình soạn thảo:

mongo-server cd ~/mongoconf 
mongo-server nano Dockerfile

 

Thêm phần sau vào tệp mới:

Dockerfile
FROM ubuntu:xenial
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
RUN echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.4.list
RUN apt-get update && apt-get install -y mongodb-org
RUN mkdir -p /mongo/db /etc/mongo
EXPOSE 28018
ENTRYPOINT ["mongod", "--config", "/etc/mongo/mongod.conf"]

Tập tin này cho thấy Docker tạo một hình ảnh dựa trên Ubuntu 16.04 Xenial, tải xuống các tệp nhị phân MongoDB mới nhất và tạo một vài thư mục nơi lưu trữ các tệp cấu hình và cơ sở dữ liệu. Nó làm cho port 28018 của container có sẵn cho máy chủ và chạy Mongo mỗi khi người dùng khởi động lại container.

Lưu ý: Để đơn giản, hình ảnh của chúng tôi là dựa trên Ubuntu. Tuy nhiên, các container được xây dựng trên các bản phân phối nhẹ như Alpine Linux sử dụng ít không gian đĩa hơn.

Lưu tệp và thoát khỏi trình chỉnh sửa của bạn. Sau đó, tạo hình ảnh:

mongo-server docker build -t mongo .
  •  

Khi hình ảnh được tạo, hãy chạy container dựa trên hình ảnh. Gắn thư mục config như một ổ đĩa bên trong container để các cấu hình và khóa tùy chỉnh của được hiển thị cho phiên bản MongoDB bên trong container:

mongo-server docker run \ 
mongo-server --detach \ 
mongo-server --publish 28018:28018 \ 
mongo-server --volume $PWD/config:/etc/mongo \ 
mongo-server --name mongodb \ 
mongo-server mongo
  •  
  •  

Bây giờ bạn có một phiên bản MongoDB đang chạy, hãy truy cập nó từ máy tính cục bộ của bạn.

 

Bước 6 - Truy cập MongoDB

Trong một thiết bị đầu cuối mới trên máy cục bộ của bạn, hãy kết nối với cơ sở dữ liệu bằng địa chỉ private IP của máy chủ MongoDB. Bạn sẽ cung cấp các tệp client.pem và server.pem mà đã tải xuống máy cục bộ, cũng như cụm mật khẩu đã sử dụng khi tạo chứng chỉ ứng dụng client. Thực hiện lệnh này như sau:

 mongo \--ssl \ 
--sslCAFile path_to_server_pem \ 
--sslPEMKeyFilepath_to_client_pem\ 
--sslPEMKeyPasswordpem_key_passphrase \ 
--host mongodb_server_private_ip\ 
--port 28018

Nếu mọi thứ đều ổn, bạn sẽ thấy dấu nhắc MongoDB.

>
  •  

Nếu lỗi xuất hiện, hãy kiểm tra kỹ xem bạn đang kết nối với private IP của máy chủ MongoDB chứ không phải đến địa chỉ IP của máy chủ VPN. Đồng thời xác minh rằng vị trí chính và cụm mật khẩu là chính xác và kết nối của bạn với VPN vẫn đang chạy.

 

Kết luận

Bây giờ bạn có một MongoDB được cấu hình tùy chỉnh đang chạy trong Docker container. Bảo mật của nó được cấp bởi xác thực máy khách-máy chủ SSL và mã hóa truyền tải. Bạn đã thêm bảo mật bổ sung bằng cách định cấu hình tường lửa để hạn chế các kết nối cơ sở dữ liệu cho các máy khách được kết nối với máy chủ VPN.

Mặc dù thiết lập này là tối ưu để thử nghiệm, hãy nhớ rằng trong môi trường sản xuất, bạn nên sử dụng cơ quan cấp chứng chỉ đáng tin cậy và các chứng chỉ đã ký. Ngoài ra, bạn phải phân tích nhu cầu bảo mật của bạn và hành động phù hợp. Ví dụ, bạn có thể muốn thiết lập người dùng, mật khẩu và vai trò trong cơ sở dữ liệu. Hướng dẫn cài đặt và bảo mật MongoDB trên Ubuntu 16.04 có thêm thông tin về việc tạo người dùng và là bước tuyệt vời tiếp theo để hướng tới một thiết lập sẵn sàng cho sự sản xuất.

Tìm hiều nhiều điều thú vị hơn tại Vicloud!