ratanon.com - developer

Stream File on Ubuntu

การป้องการไฟล์จากลิ้งตรง ด้วยการ Stream File ไฟล์ใช้เอง มาดูวิธีการ ว่าทำยังไงบ้าง สรุปไว้ด้านล่าง สำหรับกรณีศึกษานะครับ... จะทำการทดสอบกับเว็บไซต์ nunginter.com เนื่องจากระบบจะใช้รวมใน cyberpanel ดังนั้นจะไม่พยามใช้ port ที่ไม่กระทบนะครับ เช่น 8443 ,8080

สรุปขั้นตอนการตั้งค่าและการสตรีมไฟล์วิดีโอบน Ubuntu

1.การติดตั้งซอฟต์แวร์ที่จำเป็น:

  • ติดตั้ง Nginx เพื่อใช้เป็น reverse proxy
  • ติดตั้ง Certbot เพื่อขอใบรับรอง SSL
  • ติดตั้ง Flask สำหรับสร้างแอปพลิเคชันสตรีมไฟล์วิดีโอ


2.ตั้งค่า Nginx:

  • แก้ไขไฟล์คอนฟิกของ Nginx ให้ใช้พอร์ต 8080 และ 8443 เพื่อหลีกเลี่ยงการชนกับพอร์ตที่ใช้โดย LiteSpeed
  • ปิดการใช้งานไฟล์คอนฟิกดีฟอลต์ที่ประกาศฟังพอร์ต 80


3.ขอใบรับรอง SSL จาก Let's Encrypt:

  • ใช้ DNS Cloudflare Plugin ของ Certbot เพื่อขอใบรับรอง SSL โดยไม่ต้องเปิดการใช้งานพอร์ต 80 และ 443 โดยตรง


4.ตั้งค่าและทดสอบ Flask app:

  • เขียนโค้ดสำหรับแอปพลิเคชัน Flask ที่จะสตรีมไฟล์วิดีโอจาก URL โดยเข้ารหัสชื่อไฟล์เป็น Base64
  • เพิ่มการตรวจสอบ HTTP Referer เพื่อให้แน่ใจว่าไฟล์วิดีโอจะเปิดได้เฉพาะเมื่อเข้ามาจากเว็บ nunginter.com



รายละเอียดขั้นตอน การติดตั้งซอฟต์แวร์ที่จำเป็น

# ติดตั้ง Nginx
sudo apt-get update
sudo apt-get install nginx


# ติดตั้ง Certbot และ DNS Cloudflare Plugin

sudo apt-get install certbot python3-certbot-dns-cloudflare


# ติดตั้ง Flask และ CORS

sudo apt-get install python3-pip
pip3 install flask flask-cors requests


ตั้งค่า Nginx


1. สร้างไฟล์คอนฟิก Nginx สำหรับโดเมน `forward.nunginter.com`:

sudo nano /etc/nginx/sites-available/forward


เนื้อหาในไฟล์ `/etc/nginx/sites-available/forward`:

nginx
server {
  listen 8080;
  server_name forward.nunginter.com;

  location / {
    proxy_pass http://127.0.0.1:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

server {
  listen 8443 ssl;
  server_name forward.nunginter.com;

  ssl_certificate /etc/letsencrypt/live/forward.nunginter.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/forward.nunginter.com/privkey.pem;

  location / {
    proxy_pass http://127.0.0.1:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}


2. เปิดใช้งานคอนฟิก:

sudo ln -s /etc/nginx/sites-available/forward /etc/nginx/sites-enabled/


3. ปิดการใช้งานคอนฟิกดีฟอลต์:

sudo rm /etc/nginx/sites-enabled/default


4. เปิดพอร์ต 8080 และ 8443 ใน Firewall:

sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
sudo netfilter-persistent save
sudo netfilter-persistent reload


ขอใบรับรอง SSL จาก Let's Encrypt

1. สร้างไฟล์เก็บ Cloudflare API Token: https://dash.cloudflare.com/profile/api-tokens

sudo nano /root/.cloudflare_credentials


เพิ่มเนื้อหาดังนี้:

dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN


2. ขอใบรับรอง SSL:

sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cloudflare_credentials -d forward.nunginter.com



ตั้งค่าและทดสอบ Flask app

1. เขียนโค้ดสำหรับแอปพลิเคชัน Flask:

python

from flask import Flask, Response, request, abort
from flask_cors import CORS
import base64
import requests

app = Flask(__name__)
CORS(app)

ALLOWED_REFERER = "https://nunginter.com"

def get_file_from_base64(encoded_filename):
  encoded_filename = encoded_filename.replace('.mp4', '')
  decoded_bytes = base64.urlsafe_b64decode(encoded_filename)
  filename = decoded_bytes.decode('utf-8')
  return filename

@app.route('/')
def index():
  return "Flask application is running!"

@app.route('/<path:encoded_filename>.mp4', methods=['GET'])
def stream_file(encoded_filename):
  referer = request.headers.get('Referer')
  if not referer or not referer.startswith(ALLOWED_REFERER):
    return abort(403, description="Forbidden: You don't have permission to access this resource.")
   
  try:
    filename = get_file_from_base64(encoded_filename)
    url = f'https://ลิ้งตรง/{filename}'

    headers = {}
    range_header = request.headers.get('Range', None)
    if range_header:
      headers['Range'] = range_header

    response = requests.get(url, headers=headers, stream=True)

    def generate():
      for chunk in response.iter_content(chunk_size=8192):
        yield chunk

    status_code = response.status_code if range_header else 200

    response_headers = {
      'Content-Type': 'video/mp4',
      'Content-Length': response.headers['Content-Length']
    }
    if 'Content-Range' in response.headers:
      response_headers['Content-Range'] = response.headers['Content-Range']

    return Response(generate(), status=status_code, headers=response_headers)

  except Exception as e:
    return str(e), 500

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=5000)


2. รัน Flask app:

python3 nunginter.py


ตรวจสอบการทำงาน

1. ตรวจสอบว่า Nginx และ Flask ทำงานถูกต้อง:

  - เข้าถึง URL: `https://forward.nunginter.com:8443/MzAwLjIwMDYubXA0.mp4`

  - ตรวจสอบว่าการเข้าถึงจากโดเมนอื่นถูกบล็อก

  - ตรวจสอบว่าการเข้าถึงจากโดเมน `nunginter.com` ทำงานได้ตามที่คาดหวัง


2. ปรับปรุง HTML ของแท็ก `<video>` ในหน้าเว็บให้ถูกต้อง:

<video id="v_player_html5_api" class="vjs-tech" preload="auto" playsinline="playsinline" poster="https://nunginter.com/upload/movie/backdrop/511-backdrop.jpg" data-setup="{}" autoplay controls>
  <source src="https://forward.nunginter.com:8443/MzAwLjIwMDYubXA0.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video>



ขั้นตอนการสร้าง Systemd Service สำหรับรัน Flask App

1. สร้างไฟล์ Service สำหรับ Systemd:

  - สร้างไฟล์ `nunginter.service` ใน `/etc/systemd/system/`

  sudo nano /etc/systemd/system/nunginter.service


2. เพิ่มเนื้อหาดังนี้ลงในไฟล์ `nunginter.service`:

  [Unit]
  Description=Nunginter Flask App
  After=network.target

  [Service]
  User=www-data
  Group=www-data
  WorkingDirectory=/home/nunginter.com/python
  ExecStart=/usr/bin/python3 /home/nunginter.com/python/nunginter.py
  Restart=always

  [Install]
  WantedBy=multi-user.target

  - ตรวจสอบให้แน่ใจว่า `User` และ `Group` ตรงกับสิทธิ์ของผู้ใช้ที่เหมาะสม คุณสามารถใช้ `www-data` หรือผู้ใช้ที่คุณต้องการ


3. รีโหลด Systemd daemon:

  sudo systemctl daemon-reload


4. เปิดใช้งาน Service ให้เริ่มต้นอัตโนมัติเมื่อระบบเริ่มต้น:

  sudo systemctl enable nunginter


5. เริ่มต้น Service:

  sudo systemctl start nunginter


6. ตรวจสอบสถานะของ Service:

  sudo systemctl status nunginter


เมื่อรันคำสั่ง `sudo systemctl start nunginter` คุณจะได้ผลลัพธ์บางอย่างเช่น:

● nunginter.service - Nunginter Flask App
   Loaded: loaded (/etc/systemd/system/nunginter.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2024-06-20 07:30:00 UTC; 10s ago
  Main PID: 12345 (python3)
   Tasks: 1 (limit: 2212)
   Memory: 10.0M
   CPU: 50ms
   CGroup: /system.slice/nunginter.service
       └─12345 /usr/bin/python3 /home/nunginter.com/python/nunginter.py



สรุป

1. สร้างไฟล์ `nunginter.service` ใน `/etc/systemd/system/`

2. เพิ่มการตั้งค่าตามที่ระบุในไฟล์

3. รีโหลด Systemd daemon

4. เปิดใช้งานและเริ่มต้น Service

5. ตรวจสอบสถานะของ Service


ด้วยวิธีนี้ `nunginter.py` จะรันเป็นพื้นหลังและรันอัตโนมัติเมื่อระบบเริ่มต้นใหม่ และจะรีสตาร์ทอัตโนมัติหากเกิดข้อผิดพลาด


ลองดูครับหวังว่าคงมีประโยชน์สำหรับคนทีสตรีมมิ่งไว้ใช้งานเอง...

gunicorn สำหรับ prod

เพื่อให้การตั้งค่าเสถียรและมั่นใจว่าแอปพลิเคชันจะรันเป็นพื้นหลังอย่างถูกต้อง เพื่อปรับปรุงการตั้งค่าให้ใช้ Gunicorn เราจะแก้ไขไฟล์ nunginter.service และตั้งค่า Gunicorn ให้ทำงานเป็น WSGI HTTP Server สำหรับ Flask app นี่คือสรุปขั้นตอนที่ทำมาและการตรวจสอบเพิ่มเติม


### การตั้งค่า gunicorn เพื่อรันแอป Flask

1. ติดตั้ง gunicorn:

  python3 -m pip install gunicorn


2. แก้ไขไฟล์บริการ Systemd:

  สร้างหรือแก้ไขไฟล์ /etc/systemd/system/nunginter.service:

  [Unit]
  Description=Nunginter Flask App
  After=network.target

  [Service]
  User=www-data
  Group=www-data
  WorkingDirectory=/home/nunginter.com/python
  ExecStart=/usr/local/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 nunginter:app
  Restart=always

  [Install]
  WantedBy=multi-user.target


3. รีโหลด Systemd และเริ่มบริการ nunginter:

  sudo systemctl daemon-reload
  sudo systemctl start nunginter
  sudo systemctl enable nunginter


### การตั้งค่า nginx เพื่อ Proxy ไปยัง gunicorn

4. ตั้งค่า nginx:

  ตรวจสอบและแก้ไขไฟล์ /etc/nginx/sites-available/forward:

  server {
    listen 8080;
    server_name forward.nunginter.com;

    location / {
      proxy_pass http://127.0.0.1:5000;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }

  server {
    listen 8443 ssl;
    server_name forward.nunginter.com;

    ssl_certificate /etc/letsencrypt/live/forward.nunginter.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/forward.nunginter.com/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
      proxy_pass http://127.0.0.1:5000;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }
  


5. รีโหลด nginx:

  sudo systemctl reload nginx


### การตรวจสอบและทดสอบการทำงาน

6. ตรวจสอบสถานะของ gunicorn:

  sudo systemctl status nunginter

 

7. ตรวจสอบสถานะของ nginx:

  sudo systemctl status nginx


8. ทดสอบการเข้าถึงแอปพลิเคชัน:

  - ทดสอบการเข้าถึงผ่าน curl:

   curl -v https://forward.nunginter.com:8443/


  - ตรวจสอบว่าการเข้าถึงผ่านเบราว์เซอร์ทำงานได้ดีที่ URL:

   https://forward.nunginter.com:8443/

   

ส่วน code nunginter.py ที่แก้แล้วสำหรับการใช้งานกับ gunicorn

from flask import Flask, Response, request, abort
from flask_cors import CORS
import base64
import requests

app = Flask(__name__)
CORS(app)

ALLOWED_REFERER = "https://nunginter.com"

def get_file_from_base64(encoded_filename):
  encoded_filename = encoded_filename.replace('.mp4', '')
  decoded_bytes = base64.urlsafe_b64decode(encoded_filename)
  filename = decoded_bytes.decode('utf-8')
  return filename

@app.route('/')
def index():
  return "nunginter.com application is running!"

@app.route('/<path:encoded_filename>.mp4', methods=['GET'])
def stream_file(encoded_filename):
  referer = request.headers.get('Referer')
  if not referer or not referer.startswith(ALLOWED_REFERER):
    return abort(403, description="Forbidden: You don't have permission to access this resource.")

  try:
    filename = get_file_from_base64(encoded_filename)
    url = f'MY_S3/{filename}'

    headers = {}
    range_header = request.headers.get('Range', None)
    if range_header:
      headers['Range'] = range_header

    response = requests.get(url, headers=headers, stream=True)

    def generate():
      for chunk in response.iter_content(chunk_size=8192):
        yield chunk

    status_code = response.status_code if range_header else 200

    response_headers = {
      'Content-Type': 'video/mp4',
      'Content-Length': response.headers['Content-Length']
    }
    if 'Content-Range' in response.headers:
      response_headers['Content-Range'] = response.headers['Content-Range']

    return Response(generate(), status=status_code, headers=response_headers)

  except Exception as e:
    return str(e), 500

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=5000)


ถ้าทุกอย่างถูกตั้งค่าและตรวจสอบอย่างถูกต้อง จะสามารถเข้าถึงแอปพลิเคชันของคุณผ่าน HTTPS ได้โดยไม่มีปัญหา


และหวังว่าไม่ติดปัญหา 5555

0
39