Tag: nginx

  • Sử dụng Nginx để truy cập tới một Private S3 Bucket

    Sử dụng Nginx để truy cập tới một Private S3 Bucket

    Bài toán

    Mình được giao nhiệm vụ phát triển một ứng dụng quản lý chi tiêu cho khách hàng. Thông tin các hoá đơn và ảnh trong ứng dụng sẽ được lưu trên S3. Khách hàng có yêu cầu có thể xem được ảnh lưu trên S3 bằng domain của họ thay vì bằng đường link trực tiếp từ S3. Hệ thống Backend của họ đang sử dụng Nginx với Python Flask và mong muốn không sử dụng đến dịch vụ CloudFront.

    Giải pháp

    Sau hồi nguyên cứu mình đã tìm ra giải pháp là có thể dùng Nginx để truy cập tới một private S3 bucket.

    Để có thể demo được giải pháp nên mình sẽ lược bỏ hệ thống cho nó đơn giản hơn so với hệ thống của khách hàng. Đầu tiên giả sử hệ thống trên AWS đã được cấu hình như bên dưới:

    • VPC(10.0.0.0/16) với public subnet và private subnet
    • VPC Endpoint cho s3
    • A static web on ECS Fargate with Nginx
    • 1 trang web tĩnh được triển khai trên dịch vụ ECS Fargate với việc dùng Nginx
    • 1 private S3 bucket để lưu ảnh của trang web.

    Alt Text

    Kết quả sau khi cấu hình xong chúng ta sẽ có 1 trang web như bên dưới. Nhưng hình ảnh mọi nguời thấy là hình ảnh được tải từ trên mạng. Alt Text

    Bây giờ mình sẽ cần thay thể ảnh trên mạng này với ảnh trên S3. Để làm được điều đó các bạn theo dõi tiếp bên dưới nhé. Alt Text

    Thiết lập Nginx và S3

    1. Thay đổi S3 bucket policy để chỉ cho phép lấy dữ liệu từ VPC Endpoint.

    {
        "Version": "2008-10-17",
        "Id": "PolicyForCloudFrontPrivateContent",
        "Statement": [
            {
                "Sid": "Access-to-specific-VPCE-only",
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::demo-static-s3/*",
                "Condition": {
                    "StringEquals": {
                        "aws:sourceVpce": "vpce-0d92e50f230bc8070"
                    }
                }
            }
        ]
    }
    

    2. Tiếp theo là việc quan trọng nhất, chúng ta sẽ cần cấu hình Nginx để có thể tải ảnh từ private S3

    location ~^/image/(.+)$ {
            resolver 10.0.0.2;
            proxy_pass http://s3-ap-southeast-1.amazonaws.com/demo-static-s3/image/$1; 
    }
    
    • resolver: Địa chỉ IP của DNS server trong VPC mà mình đã tạo.

      Ví dụ, VPC của mình tạo có CIRD là 10.0.0.0/16. AWS sẽ dùng 5 IPs bên dưới cho các mục đích bên của họ và mình sẽ không thể sử dụng các IP đó.

      • 10.0.0.0: Network address.
      • 10.0.0.1: Reserved by AWS for the VPC router.
      • 10.0.0.2: Reserved by AWS. The IP address of the DNS server is the base of the VPC network range plus two. For VPCs with multiple CIDR blocks, the IP address of the DNS server is located in the primary CIDR. We also reserve the base of each subnet range plus two for all CIDR blocks in the VPC. For more information, see Amazon DNS server.
      • 10.0.0.3: Reserved by AWS for future use.
      • 10.0.0.255: Network broadcast address. We do not support broadcast in a VPC, therefore we reserve this address.

      => Resolver sẽ có giá trị là 10.0.0.2

      Tham khảo: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html

    • proxy_pass: s3 link

      Định dạng: http://s3-ap-southeast-1.amazonaws.com/[main_bucket]/[sub_bucket]/$1

    3. Thay đổi dường dẫn của tải ảnh của trang web

    <div class="container">
        <h1>Hey there</h1>
        <img src="https://cleandevs.com/image/668c1d479e27bb8750823655c83a6c9bd90263f9_hq.jpg"/>
      </div>
    

    4. Cuối cùng mình sẽ deploy lại trang web lên dịch vụ ECS Fargate. Kết quả sẽ như hình bên dưới. Trang web đã hiển thị ảnh được tải từ private S3 bucket

    Alt Text

  • Webserver (Part 2)

    Webserver (Part 2)

    Trong Phanaf

    Trong phần trước, mình đã đề cập đến Host, WebServer. Vậy magz.techover.io hay google.com từ đâu mà có. Phần này sẽ tiếp tục với DNS.

    DNS

    Như phần trước, chúng ta có Host header, header này báo cho WebServer website mà client yêu cầu, vậy làm cách nào mà khi chúng ta điền google.com lên thanh URL và request đó đến đựoc WebServer?

    Đó chính là nhiệm vụ của DNS – Domain Name Service, đúng như cái tên nó là một service cung cấp tên miền (Domain Name). Khi chúng ta mua domain từ một nhà cung cấp (ví dụ như godaddy.com, hay namecheap.com), chúng ta thường thêm một số Domain Name Server vào domain đó. Nó sẽ kiểu như này:

    Domain name Server của một domain sử dụng AWS Route53

    Thực ra vụ này cũng không cần thiết lắm, vì nhiều nhà cung cấp cài đặt sẵn cho mọi người rồi, mọi người chỉ cần làm việc này khi chuyển việc quản lý domain cho service khác thôi (ví dụ khi mua bạn mua ở namecheap.com) và bạn chuyển qua cloudflare.com)), và chuyện này cũng phổ biến và thậm chí được khuyên dùng, lý do: security và high availability. Nhiều Name Server đã bị tấn công nhiều lần, khi đó, DNS sẽ không hoạt động và tất nhiên trang web của bạn cũng không thể truy cập bằng domain. Dùng nhiều DNS khác nhau cũng là một cách, vì bạn có thể setup nhiều ns record, một cách dễ hiểu là đừng bỏ trứng vào chung rổ và tất nhiên có nhiều bên cung cấp service này:

    • AWS Route 53
    • CloudFlare DNS
    • DynDNS
    • OpenDNS
    • EasyDNS
    • DNSMadeEasy

    Một khi Name Server của bạn được cài đặt, bạn có thể bắt đầu tạo DNS record ở trang web hay công cụ của nhà cung cấp Domain, đợi một vài phút là bạn có thể truy cập trang web của bạn từ trình duyệt.

  • Webservers

    Webservers

    Về cơ bản bài viết này đưa cho các bạn khái niệm rất cơ bản về WebServer, các bạn web developer có thể rất cần Đầu tiên, mình nghĩ chúng ta nên đề cập đến HTTP, làm thế nào để match incoming HTTP request với website, sau đó là 2 Web Server rất phổ biến: Apache và Nginx, cuối cùng sẽ đề cập đến 1 ngôn ngữ cụ thể và cách kết nối với web server ở đây là PHP với PHP-FPM.

    HTTP, Web Server và Web Sites

    Mọi người có lẽ đều nghĩ rằng một WebServer chỉ có thể xử lý phục vụ một trang web, nhưng thực sự là ngược lại. Trong Apache thì dùng khái niệm VirtualHost, còn Nginx sử dụng bằng cách định nghĩa Server trong Nginx Configuration hay còn gọi là Virtual Servers.

    Nếu một WebServer đang xử lý nhiều trang web, làm thế nào để máy chủ định tuyến đến đúng trang web mà người dùng muốn truy cập?

    Chúng ta quay lại với HTTP – HyperText Transfer Protocol, là một trong năm giao thức chuẩn của mạng Internet, giao thức sử dụng để giao tiếp giữa WebServer và WebClient. Về cơ bản, WebServers sẽ đọc Host header của các Web HTTP request, nếu không tồn tại Host header hoặc không phù hợp, WebServer sẽ chuyển yêu cầu đến một trang web mặc định.

    Chúng ta có thể dùng curl để kiểm tra. Ví dụ mình sẽ kiểm tra magz.techover.io và Google.

    Chúng ta có thể thấy IP của WebServer là 104.28.19.140, chúng ta dùng curl để xem response khi gọi đến địa chỉ này.

    Chúng ta có thể thấy là magz.techover.io sử dụng Cloudflare để bảo vệ, và chúng ta bị chuyển đến trang mặc định 403 khi không có quyền truy cập.

    Còn với Google:

    Có thể thấy Google sử dụng GWS – Google Web Server. GWS thông báo cho Client rằng, Client cần phải truy cập đến http://www.google.com thông qua Location Header. Có 2 điều bạn thấy ở đây:

    • http://www.google.com mới là trang mặc định, thay vì http://google.com (cái này liên quan đến một khái niệm khác http://google.com được gọi là Naked Domain Name, sẽ có một bài viết liên quan đến vụ này sau).
    • GWS gửi một response chuyển hướng 301 đến http://www.google.com.

    Bây giờ nếu thêm Host header vào trang web thì sao:

    Kết quả không khả quan lắm, có vẻ như magz.techover.io và google.com vẫn không phải trang mặc định. Với trường hợp của magz.techover.io là do cloudflare chuyển hướng với non-SSL request sang SSL site.

    Đến đây một session mới được khởi tạo với Set-Cookie Header. Chúng ta có thể thử với một static site khác, site này không hề có Set-Cookie Header.

    Phần tiếp theo sẽ nói về việc cài đặt và cấu hình Nginx và Apache cho một hoặc nhiều Website.