- vừa được xem lúc

Deta - micro server miễn phí dành cho dev

0 0 30

Người đăng: Nguyen Anh Tien

Theo Viblo Asia

Mở đầu

Đôi khi chúng ta cần một web server đơn giản, public ra internet để thực thi vài tác vụ linh tinh, hoặc để hosting một số file khi cần. Tuy nhiên, với tư cách là một dev/pentester "nhà nghèo" thì việc có thẻ visa để đăng ký free cloud của Google, AWS, Oracle thôi nhiều khi đã là cả một vấn đề lớn 🤣. Đùa chút thôi, bài viết này mình sẽ giới thiệu Deta - một công cụ cho phép bạn nhanh chóng tạo micro-website/API và public ra internet. Here we go~

Deta

https://deta.sh là công cụ Cloud cá nhân miễn phí cho phép chúng ta xây dựng các ứng dụng, prototype rồi public ra internet một cách nhanh chóng.

Deta đi kèm với:

  • Deta Base: NoSQL database (giống như MongoDB)
  • Deta Micros: Cho phép bạn deploy ứng dụng của mình lên internet (giống như Heroku). Deta cho tạo thoải mái bao nhiêu micros cũng được hết 😳
  • Deta Drive: Cho phép lưu trữ file (giống như Google Drive và AWS S3)

Deta hiện đang hỗ trợ các ngôn ngữ: Python, Node.js, và Golang. Với mỗi ngôn ngữ, Deta cũng hỗ trợ các micro-framework ví dụ như Python là FastAPI hoặc Flask.

Để lấy ví dụ, mình sẽ xây dựng ứng dụng đơn giản dành cho pentester như sau:

  1. Cho phép tải file lên theo URL và MIME Type tùy ý. VD: truy cập vào link: "https://myfakeserver.com/aaa.png" nhưng trả ra content là alert(origin) và mime type lại là javascript (chứ không phải file ảnh như đuôi PNG).
  2. Cho người dùng điền trực tiếp nội dung file.
  3. Cho phép xoá file.

Cài đặt

Tất cả hướng dẫn sử dụng (đầy đủ và chi tiết) đều có ở https://docs.deta.sh/docs/home

Trước hết là chúng ta cần đăng ký tài khoản. Màn hình quản lý nằm ở: https://web.deta.sh/home

Sau đó, ta tải về Deta CLI rồi đăng nhập:

curl -fsSL https://get.deta.dev/cli.sh | sh
deta login

sau đó tạo một micro mới với framework là python:

deta new payload-server --python Successfully created a new micro
{ "name": "payload-server", "id": "xxxxxx", "project": "xxxxxxx", "runtime": "python3.9", "endpoint": "https://xxxxxxx.deta.dev", "region": "ap-southeast-1", "visor": "disabled", "http_auth": "disabled"
}

xem thử file vừa tạo:

➜ payload-server cat main.py
def app(event): return "Hello, world!"%

Ngay ở bước này chúng ta có thể chạy deta deploy và app của chúng ta sẽ được deploy lên URL ở trên. Quá nhanh, quá nguy hiểm:

Chúng ta cũng có thể cài đặt thêm các thư viện, tạo file requirements.txt và điền tên các thư viện vào, ở đây ta sẽ cần đến Flask và Deta

flask
deta

Mỗi lần sửa code xong xuôi thì nhớ deta deploy để đẩy code lên nhé

Backend

Sửa lại file main.py như sau, vì code cũng khá ngắn có 88 dòng và đơn giản nên mình sẽ không đi vào từng bước mà chỉ giải thích một số vị trí quan trọng.

from flask import Flask
from flask import Flask, request, render_template, abort, Response, flash, redirect
from deta import Deta
import uuid app = Flask(__name__) app.secret_key = b'somethingrandom' deta = Deta("PROJECT_KEY_HERE")
drive = deta.Drive("files")
db = deta.Base("payload_db") @app.route("/", defaults={"path": ""}, methods=["GET", "POST"])
@app.route("/<path:path>")
def catch_all(path): if path == "": if request.method == 'POST': return upload() else: res = db.fetch() all_items = res.items return render_template("index.html", items=all_items) elif path == "delete": return delete() else: return download(path) def upload(): file = request.files.get("file") submitted_mime = request.form.get("mime") submitted_path = request.form.get("path") content = request.form.get("content") mime = "text/plain" if submitted_mime: mime = submitted_mime if file: mime = file.content_type content = file elif not content: flash("[ERROR] No content!") return redirect("/") if not submitted_path: flash("[ERROR] No path!") return redirect("/") if db.fetch({"path": submitted_path}, limit=1).items: flash("[ERROR] Duplicate path!") return redirect("/") filename = str(uuid.uuid4()) db.put({"path": submitted_path, "filename": filename, "mime": mime}) res = drive.put(filename, content, content_type=mime) if res: flash(f"[OK] file uploaded to path: {submitted_path}") return redirect("/") def download(path): items = db.fetch({"path": path}, limit=1).items if items: file = drive.get(items[0]['filename']) content = file.read() file.close() return Response(content, mimetype=items[0]['mime']) else: return abort(404) def delete(): path = request.args.get("p") items = db.fetch({"path": path}, limit=1).items if items: db.delete(items[0]['key']) drive.delete(items[0]['filename']) flash(f"[OK] path '{path}' deleted!") return redirect("/") else: return abort(404) # Uncomment this line to debug local
# app.run()

Ở đoạn này chúng ta cần tạo Project Keys (tương tự API key) trong giao diện ở dưới, drivedb là các object giúp chúng ta tương tác với database và drive:

deta = Deta("PROJECT_KEY_HERE")
drive = deta.Drive("files")
db = deta.Base("payload_db")

Phần route, chúng ta sẽ tạo một route dùng để catch all (bắt tất cả các request) rồi kiểm tra:

  • Nếu là path index => chuyển đến trang upload.
  • Nếu là path delete => chuyển đến trang xoá file
  • Còn lại thì mặc định là xử lý trả về nội dung file (nếu có tồn tại)

Deta đã cũng cấp sẵn cho chúng ta các phương thức để tương tác với DB:

db.put({"path": submitted_path, "filename": filename, "mime": mime})

Dùng để insert một bản ghi vào DB. Chúng ta sẽ lưu lại path (để kiểm tra xem có bị trùng không), filename thì sinh ngẫu nhiên bằng uuid, mime do người dùng tự nhập hoặc lấy ra từ file tải lên. Dữ liệu trong DB sẽ có dạng sau:

{'filename': 'ee8945e3-b7aa-4d0a-829a-b472aecb1ef2', 'key': '2zd58xhd6hvi', 'path': 'abc.png'}
db.fetch({"path": submitted_path}, limit=1)

dùng để lấy ra dữ liệu, có thể query chính xác hoặc theo syntax gần với MongoDB: https://docs.deta.sh/docs/base/queries.

db.delete(items[0]['key'])

Dùng để xóa file dựa theo key. Ta cũng có thể tương tác trực tiếp thông qua giao diện ở https://web.deta.sh/home:

Rất đơn giản đúng không nào? Tương tác với Drive cũng hoàn toàn tương tự:

# Upload file
drive.put(filename, content, content_type=mime) # Đọc nội dung file
file = drive.get(items[0]['filename'])
content = file.read()
file.close() # Xóa file theo filename 
drive.delete(items[0]['filename'])

Drive cũng có giao diện trực quan:

Frontend

Không màu mè, hoa lá, giao diện thuần HTML, no CSS 🤣

<!DOCTYPE html>
<html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Payload Server</title>
</head>
<body> <h1>Payload Server</h1> {% with messages = get_flashed_messages() %} {% if messages %} <ul> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %} <h2>Upload</h2> <form action="/" enctype="multipart/form-data" method="post"> <input name="file" type="file"><br><br> <label for="path">URL Path</label> <input name="path" type="text"><br><br> <label for="mime">MIME (default to <code>text/plain</code> or file's mime)</label> <input name="mime" type="text"><br><br> <label for="path">Content (if no file is selected)</label> <textarea name="content" id="content" cols="50" rows="5"></textarea><br><br> <input type="submit"> </form> <h2>List payloads</h2> {% if items %} <ul> {% for item in items %} {% set p = item['path']%} <li><a href="/{{p}}">/{{p}}</a> - <a href="/delete?p={{p}}">Delete</a></li> {% endfor %} </ul> {% endif %}
</body>
</html>

It's Demo Time

Chạy deta deloy và xem thành quả thôi: https://8r8cjf.deta.dev/

Giới hạn

Tất nhiên là với dịch vụ Free như thế này thì sẽ đi kèm với một số giới hạn chính sau:

  • Các micros thực tế là chạy trên Lambda nên thời gian khởi động (sau khi sleep) sẽ có thể bị chậm.
  • RAM chỉ có 512MB.
  • Các request sẽ time-out sau 10 giây, nên không thể chạy các process trong thời gian dài.
  • Nếu không upload lên Drive thì chỉ có thể upload lên thư mục /tmp/.
  • Drive có dung lượng 10GB.
  • Thư viện tối đa 250 MB, source code tối đa 250MB.

Chi tiết hơn ở: https://docs.deta.sh/docs/micros/about

Nhưng với mục đích để prototype và demo thì thế này vẫn quá là OK la 😊

Ngoài ra còn gì?

Deta còn cung cấp một số tiện ích khá hữu ích:

  • Deta Crons cho phép chạy các task theo định kỳ (như cronjob trong Linux).
  • Deta Visor cho phép chúng ta xem log request/response đến micro và log lỗi.
  • Cho phép custom subdomain (VD: https://myserver.deta.dev/) và domain riêng, quá tiện lợi cho các anh em dev làm web mời cưới 😅

Kết

Chúc mọi người tận dụng Deta hiệu quả và có nhiều ý tưởng hay ho nhá 😀

Bình luận

Bài viết tương tự

- vừa được xem lúc

Các nguyên tắc bảo mật cơ bản trên Amazon Web Services (P1)

Lời mở đầu. Từ lưu trữ dữ liệu, chia sẻ file, truy cập từ xa, đến sao lưu từ xa – điện toán đám mây là một nhân tố quan trọng trong CNTT hiện đại.

0 0 51

- vừa được xem lúc

Serverless Computing in 100 Seconds

Serverless Computing can dramatically simplify your backend infrastructure by eliminating the need to configure, maintain, and scale servers. Go beyond 100 seconds with @FilledStacks to build a produc

0 0 36

- vừa được xem lúc

Is Supabase Legit? Firebase Alternative Breakdown

Supabase is a new open-source "Firebase Alternative". Let's compare features, pricing, and the developer experience to see how Supabase stacks up to Firebase https://fireship.io. .

0 0 36

- vừa được xem lúc

Làm việc tại nhà an toàn hơn với VPN của riêng bạn - Hoàn toàn miễn phí

Mở đầu. Lại một đợt dịch mới quay lại với nhiều tin tức xấu hơn sau mỗi lần bùng phát, cũng vì thế là công việc WORK FROM HOME lại quay trở lại với rất nhiều ngành nghề và đặc biệt là anh em IT.

0 0 44

- vừa được xem lúc

Một con vịt đi vào quán bar

Một con vịt đi vào quán bar, vịt hỏi bartender: "Mày có nhìn thấy anh trai tao không?". Bartender trả lời: "Anh mày nhìn như thế nào?".

0 0 43

- vừa được xem lúc

Top 50+ AWS Services Explained in 10 Minutes (or so)

Amazon Web Services (AWS) is the world's largest and most complex cloud with over 200 unique services. Learn about the top 50 cloud products in just ten minutes. https://fireship.io/pro.

1 1 38