Tác giả: Biên Tập Viên

  • Cài Git xong rồi… nhưng chưa dùng được gì

    Cài Git xong rồi… nhưng chưa dùng được gì

    Nhiều bạn mới học Git hay gặp cảnh này: cài xong, gõ git commit lần đầu thì Git hỏi ngược lại “bạn là ai?” — và không biết phải trả lời như thế nào. Hoặc clone repo về thì bị lỗi authentication, nhập password mãi không xong.

    Bài này giải quyết đúng điểm đó. Sau khi đọc xong, bạn sẽ có một môi trường Git hoàn chỉnh: cài đặt, cấu hình danh tính, kết nối SSH với GitHub/GitLab — và sẵn sàng bắt đầu làm việc thật sự.

    Cài đặt Git

    Windows

    Tải Git for Windows tại git-scm.com. Trong quá trình cài, có vài lựa chọn quan trọng:

    • Default editor: chọn VS Code nếu bạn đang dùng, hoặc Notepad++ — tránh chọn Vim nếu chưa quen
    • LINE ENDING conversions: chọn “Checkout Windows-style, commit Unix-style” — đây là lựa chọn an toàn nhất khi làm việc với team đa nền tảng
    • Các mục còn lại giữ mặc định

    Sau khi cài, mở Git Bash (đã được cài kèm) và kiểm tra:

    git --version
    # git version 2.44.0.windows.1

    macOS

    Cách nhanh nhất là dùng Homebrew:

    brew install git

    Nếu chưa có Homebrew, có thể cài qua Xcode Command Line Tools:

    xcode-select --install

    macOS mới thường đã có Git sẵn, nhưng phiên bản cũ. Homebrew cho bạn bản mới nhất.

    Linux (Ubuntu/Debian)

    sudo apt update
    sudo apt install git

    Fedora/RHEL:

    sudo dnf install git

    Cấu hình danh tính — Bước không thể bỏ qua

    Git cần biết bạn là ai trước khi cho phép commit. Đây không phải thông tin đăng nhập — mà là chữ ký đính kèm mỗi commit bạn tạo ra. Team của bạn sẽ thấy tên này trong git log.

    git config --global user.name "Nguyen Van A"
    git config --global user.email "[email protected]"

    Dùng đúng email bạn đăng ký GitHub/GitLab — GitHub dùng email này để liên kết commit với tài khoản của bạn (avatar, contribution graph, v.v.).

    Cấu hình editor mặc định

    Khi git cần bạn nhập nội dung (ví dụ: commit message dài, rebase interactive), nó sẽ mở editor này:

    # VS Code
    git config --global core.editor "code --wait"
    
    # Vim
    git config --global core.editor "vim"
    
    # Nano (dễ hơn Vim cho người mới)
    git config --global core.editor "nano"

    Nếu dùng VS Code, flag --wait rất quan trọng — nó bảo Git chờ cho đến khi bạn đóng tab trong VS Code mới tiếp tục.

    Cấu hình mặc định branch name

    Git mới (từ 2.28) cho phép đặt tên branch mặc định. Hiện nay chuẩn ngành dùng main thay vì master:

    git config --global init.defaultBranch main

    Kiểm tra toàn bộ cấu hình

    git config --list --global

    Cấu hình được lưu ở file ~/.gitconfig. Bạn có thể mở trực tiếp để xem:

    cat ~/.gitconfig

    Output sẽ trông như thế này:

    [user]
        name = Nguyen Van A
        email = [email protected]
    [core]
        editor = code --wait
    [init]
        defaultBranch = main

    Ba cấp độ cấu hình Git

    Git có 3 cấp cấu hình, ưu tiên từ cao xuống thấp:

    Cấp Flag Lưu ở đâu Phạm vi
    Local --local .git/config Chỉ repo hiện tại
    Global --global ~/.gitconfig Tất cả repo của user
    System --system /etc/gitconfig Tất cả user trên máy

    Ví dụ thực tế: bạn làm freelance cho 2 công ty khác nhau — 1 cái muốn dùng email cá nhân, 1 cái muốn email công ty. Giải pháp:

    # Cấu hình global: email cá nhân (mặc định)
    git config --global user.email "[email protected]"
    
    # Vào repo của công ty, override local
    cd ~/work/company-project
    git config --local user.email "[email protected]"

    Kết nối SSH với GitHub/GitLab

    Đây là phần nhiều người ngại nhất — nhưng thực ra chỉ cần làm một lần. Sau đó bạn push/pull không cần nhập password nữa.

    Tại sao SSH thay vì HTTPS?

    GitHub đã tắt xác thực bằng password thường từ 2021. Nếu dùng HTTPS, bạn phải dùng Personal Access Token — dài và khó nhớ. SSH tiện hơn nhiều: generate một lần, dùng mãi.

    Bước 1: Tạo SSH key

    ssh-keygen -t ed25519 -C "[email protected]"

    Terminal sẽ hỏi:

    • Enter file to save the key: nhấn Enter để dùng đường dẫn mặc định (~/.ssh/id_ed25519)
    • Enter passphrase: có thể để trống, hoặc đặt passphrase để bảo mật hơn

    Sau khi chạy, bạn sẽ có 2 file:

    • ~/.ssh/id_ed25519 — private key, KHÔNG bao giờ chia sẻ
    • ~/.ssh/id_ed25519.pub — public key, cái này sẽ add vào GitHub

    Bước 2: Thêm vào SSH agent

    # Khởi động SSH agent
    eval "$(ssh-agent -s)"
    
    # Thêm key vào agent
    ssh-add ~/.ssh/id_ed25519

    Trên macOS, thêm vào ~/.ssh/config để key tự động load khi khởi động:

    Host github.com
      AddKeysToAgent yes
      UseKeychain yes
      IdentityFile ~/.ssh/id_ed25519

    Bước 3: Copy public key

    # macOS
    pbcopy < ~/.ssh/id_ed25519.pub
    
    # Linux
    cat ~/.ssh/id_ed25519.pub
    # Rồi copy thủ công
    
    # Windows (Git Bash)
    clip < ~/.ssh/id_ed25519.pub

    Bước 4: Add vào GitHub

    1. Vào GitHub → Settings → SSH and GPG keys → New SSH key
    2. Title: đặt tên dễ nhận ra, ví dụ “MacBook Pro 2024” hoặc “Dell Work Laptop”
    3. Key type: Authentication Key
    4. Key: paste public key vừa copy
    5. Click Add SSH key

    Bước 5: Kiểm tra kết nối

    ssh -T [email protected]

    Nếu thành công sẽ thấy:

    Hi nguyenvana! You've successfully authenticated, but GitHub does not provide shell access.

    Đừng lo về dòng “does not provide shell access” — đó là bình thường, Git hoạt động qua SSH protocol riêng.

    GitLab thì sao?

    Tương tự GitHub, chỉ khác URL kiểm tra:

    ssh -T [email protected]
    # Welcome to GitLab, @nguyenvana!

    Làm việc với nhiều tài khoản Git

    Trường hợp hay gặp: bạn có tài khoản GitHub cá nhân và tài khoản GitHub/GitLab công ty, cần dùng trên cùng 1 máy.

    Tạo thêm SSH key thứ hai:

    ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_work

    Thêm vào ~/.ssh/config:

    Host github.com
      HostName github.com
      User git
      IdentityFile ~/.ssh/id_ed25519
    
    Host github-work
      HostName github.com
      User git
      IdentityFile ~/.ssh/id_ed25519_work

    Khi clone repo của công ty, dùng host alias thay vì github.com:

    # Thay vì:
    git clone [email protected]:company/repo.git
    
    # Dùng:
    git clone git@github-work:company/repo.git

    Một số alias tiện dụng để bắt đầu

    Git alias giúp bạn gõ lệnh ngắn hơn. Đây là một số alias mình hay dùng:

    git config --global alias.st status
    git config --global alias.co checkout
    git config --global alias.br branch
    git config --global alias.lg "log --oneline --graph --decorate --all"

    Sau đó bạn có thể gõ git st thay vì git status, hoặc git lg để xem lịch sử commit dạng đẹp.

    Lỗi hay gặp khi mới setup

    “Permission denied (publickey)”

    SSH key chưa được add đúng. Kiểm tra lại:

    ssh -vT [email protected]

    Flag -v hiện chi tiết quá trình kết nối, giúp xác định đang dùng key nào và lỗi ở đâu.

    “Please tell me who you are”

    Chưa cấu hình user.nameuser.email. Chạy lại:

    git config --global user.name "Tên của bạn"
    git config --global user.email "[email protected]"

    “warning: LF will be replaced by CRLF”

    Cảnh báo về line ending trên Windows. Không phải lỗi — nhưng nếu muốn tắt:

    git config --global core.autocrlf true   # Windows
    git config --global core.autocrlf input  # macOS/Linux

    Tổng kết

    Bạn vừa hoàn thành setup Git từ đầu đến cuối. Checklist nhanh:

    • ✅ Cài Git và kiểm tra phiên bản
    • ✅ Cấu hình user.nameuser.email
    • ✅ Chọn editor mặc định
    • ✅ Tạo SSH key và kết nối với GitHub/GitLab
    • ✅ Kiểm tra bằng ssh -T [email protected]

    Môi trường đã sẵn sàng. Bài tiếp theo chúng ta sẽ đi vào trung tâm của Git: Repository, Working Tree và Staging Area — 3 khái niệm cốt lõi mà nếu hiểu đúng ngay từ đầu, bạn sẽ không bao giờ bị “lạc” khi dùng Git nữa.

  • Networking cơ bản: Kết nối, kiểm tra và bảo vệ

    Networking cơ bản: Kết nối, kiểm tra và bảo vệ

    Sau khi đã nắm được process và monitoring ở bài trước, hôm nay chúng ta đi vào một chủ đề không thể thiếu trong công việc thực chiến: networking trên Linux. Từ việc kiểm tra IP, troubleshoot kết nối, đến cấu hình firewall và SSH hardening — đây là những kỹ năng bạn sẽ dùng hàng ngày khi vận hành server hoặc làm DevSecOps.

    1. Kiểm tra thông tin mạng với ip

    Lệnh ip là công cụ hiện đại thay thế cho ifconfig (đã bị deprecated). Đây là lệnh bạn cần biết đầu tiên:

    # Xem tất cả network interfaces và địa chỉ IP
    ip addr show
    ip a   # viết tắt
    
    # Xem routing table
    ip route show
    ip r
    
    # Xem ARP cache (MAC address của các host trong mạng LAN)
    ip neigh
    
    # Bật/tắt interface
    ip link set eth0 up
    ip link set eth0 down
    
    # Thêm IP tạm thời (mất sau reboot)
    ip addr add 192.168.1.100/24 dev eth0

    Output của ip a trông như thế này:

    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
        link/ether 00:1a:2b:3c:4d:5e brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0
        inet6 fe80::21a:2bff:fe3c:4d5e/64 scope link

    SecOps note: Khi incident response, ip aip r là hai lệnh đầu tiên để xác định vị trí máy trong mạng, kiểm tra có interface lạ nào không (ví dụ attacker tạo tunnel interface).

    2. Kiểm tra kết nối và port với ssnetstat

    ss (socket statistics) nhanh hơn netstat và là lựa chọn ưu tiên trên hệ thống hiện đại:

    # Xem tất cả TCP connections đang LISTEN
    ss -tlnp
    
    # Xem tất cả UDP
    ss -ulnp
    
    # Xem tất cả connections (TCP + UDP)
    ss -tunap
    
    # Lọc theo port
    ss -tlnp sport = :80
    
    # netstat tương đương (nếu máy chưa có ss)
    netstat -tlnp
    netstat -an | grep ESTABLISHED

    Giải thích các flags: -t TCP, -u UDP, -n không resolve hostname (nhanh hơn), -a tất cả state, -p hiện process đang dùng socket, -l chỉ listening.

    SecOps note: ss -tlnp là lệnh kinh điển để phát hiện backdoor. Nếu có port lạ đang LISTEN mà bạn không biết là service gì — red flag ngay. Kết hợp với lsof -i :[port] để xem process nào đang dùng port đó.

    3. Ping, traceroute và kiểm tra DNS

    Ping — test connectivity cơ bản

    # Ping 5 gói tin
    ping -c 5 google.com
    
    # Ping với interval 0.2s (flood test, cần root)
    ping -i 0.2 -c 100 192.168.1.1
    
    # Ping IPv6
    ping6 ::1

    Traceroute — theo dõi đường đi của packet

    # traceroute dùng UDP (default)
    traceroute google.com
    
    # traceroute dùng ICMP (giống Windows tracert)
    traceroute -I google.com
    
    # mtr — kết hợp ping + traceroute, realtime
    mtr google.com
    mtr --report google.com   # output 1 lần, dùng cho scripting

    dig — kiểm tra DNS như pro

    # Query A record
    dig google.com A
    
    # Query MX record (mail server)
    dig google.com MX
    
    # Query từ DNS server cụ thể
    dig @8.8.8.8 google.com
    
    # Query ngắn gọn
    dig +short google.com
    
    # Reverse lookup (IP → hostname)
    dig -x 8.8.8.8
    
    # Trace toàn bộ DNS resolution
    dig +trace google.com

    File cấu hình DNS của hệ thống:

    # DNS server hệ thống dùng
    cat /etc/resolv.conf
    
    # Override hostname resolution (ưu tiên hơn DNS)
    cat /etc/hosts
    
    # Thứ tự lookup: /etc/nsswitch.conf
    grep hosts /etc/nsswitch.conf

    SecOps note: Attacker thường sửa /etc/hosts để redirect traffic hoặc bypass DNS. Kiểm tra file này khi điều tra incident. Cũng cần monitor /etc/resolv.conf — DNS hijacking sẽ thay đổi file này.

    4. curl — HTTP từ command line

    curl là công cụ đa năng để làm việc với HTTP, HTTPS, FTP và nhiều protocol khác:

    # GET request đơn giản
    curl https://example.com
    
    # Chỉ lấy headers
    curl -I https://example.com
    
    # POST với JSON body
    curl -X POST https://api.example.com/data 
      -H "Content-Type: application/json" 
      -d '{"key": "value"}'
    
    # Kèm authentication
    curl -u username:password https://api.example.com
    curl -H "Authorization: Bearer TOKEN" https://api.example.com
    
    # Download file
    curl -O https://example.com/file.tar.gz
    curl -L -o output.html https://example.com   # theo redirect
    
    # Verbose output để debug
    curl -v https://example.com
    
    # Test SSL/TLS
    curl -v --tlsv1.2 https://example.com 2>&1 | grep "SSL connection"
    
    # Ignore certificate errors (KHÔNG dùng trong production)
    curl -k https://example.com

    SecOps note: Khi kiểm tra API endpoint nội bộ hay điều tra một service, curl -v cho thấy đầy đủ request/response headers — rất hữu ích khi debug auth issues hoặc kiểm tra security headers (HSTS, CSP, X-Frame-Options).

    5. Firewall: iptables, nftables và UFW

    Hiểu kiến trúc: iptables và nftables

    Linux firewall hoạt động ở kernel level thông qua Netfilter. Có hai frontend chính:

    • iptables: tool truyền thống, vẫn phổ biến rộng rãi
    • nftables: thay thế hiện đại, syntax sạch hơn, Ubuntu 20.04+ dùng mặc định
    • UFW (Uncomplicated Firewall): wrapper đơn giản cho iptables/nftables, dễ dùng

    UFW — firewall đơn giản cho người mới

    # Kiểm tra trạng thái
    sudo ufw status verbose
    
    # Bật UFW
    sudo ufw enable
    
    # Allow/deny port
    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw deny 23/tcp   # block telnet
    
    # Allow từ IP cụ thể
    sudo ufw allow from 192.168.1.0/24 to any port 5432
    
    # Xóa rule
    sudo ufw delete allow 80/tcp
    
    # Default policy: deny inbound, allow outbound
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    
    # Xem numbered rules (để xóa theo số)
    sudo ufw status numbered
    sudo ufw delete 3   # xóa rule số 3

    iptables — kiểm soát chi tiết hơn

    # Xem rules hiện tại
    sudo iptables -L -v -n
    
    # Xem NAT rules
    sudo iptables -t nat -L -v -n
    
    # Block một IP
    sudo iptables -A INPUT -s 1.2.3.4 -j DROP
    
    # Allow SSH chỉ từ một subnet
    sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT
    sudo iptables -A INPUT -p tcp --dport 22 -j DROP
    
    # Lưu rules (Ubuntu/Debian)
    sudo iptables-save > /etc/iptables/rules.v4
    
    # Restore rules
    sudo iptables-restore < /etc/iptables/rules.v4

    SecOps note: Luôn có rule “allow established connections” trước khi block để không tự lock-out khỏi SSH:

    sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

    6. tcpdump — bắt packet để phân tích

    tcpdump là công cụ bắt network packet ngay trên command line — không cần GUI như Wireshark:

    # Bắt packet trên interface eth0
    sudo tcpdump -i eth0
    
    # Bắt packet liên quan đến port 80
    sudo tcpdump -i eth0 port 80
    
    # Bắt packet từ/đến một IP
    sudo tcpdump -i eth0 host 192.168.1.100
    
    # Lọc HTTP GET requests
    sudo tcpdump -i eth0 -A 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
    
    # Lưu ra file để phân tích bằng Wireshark
    sudo tcpdump -i eth0 -w capture.pcap
    
    # Đọc file pcap
    tcpdump -r capture.pcap
    
    # Bắt với output dễ đọc hơn (-n: không resolve hostname, -X: hex+ASCII)
    sudo tcpdump -i eth0 -nX port 443
    
    # Bắt ICMP (ping)
    sudo tcpdump -i any icmp

    SecOps note: tcpdump rất hữu ích khi điều tra data exfiltration hoặc C2 communication. Bắt traffic từ một process cụ thể:

    # Lấy PID của process
    ss -tlnp | grep :4444
    
    # Dùng cgroup hoặc kết hợp với strace để correlate
    sudo tcpdump -i any -n 'host [ip_suspicious]' -w suspicious.pcap

    7. SSH: Kết nối an toàn và cấu hình đúng chuẩn

    SSH cơ bản

    # Kết nối SSH
    ssh [email protected]
    ssh -p 2222 user@hostname   # port khác
    
    # Tạo SSH key pair
    ssh-keygen -t ed25519 -C "[email protected]"
    # Ed25519 là thuật toán hiện đại, an toàn hơn RSA 2048
    
    # Copy public key lên server
    ssh-copy-id user@hostname
    
    # Kết nối dùng key cụ thể
    ssh -i ~/.ssh/id_ed25519 user@hostname

    SSH config file — tiết kiệm thời gian gõ lệnh

    # ~/.ssh/config
    Host myserver
        HostName 192.168.1.10
        User admin
        Port 2222
        IdentityFile ~/.ssh/id_ed25519
        ServerAliveInterval 60
    
    # Sau đó chỉ cần gõ:
    ssh myserver

    SSH ProxyJump — kết nối qua bastion host

    # Kết nối đến internal-server qua bastion
    ssh -J [email protected] user@internal-server
    
    # Trong ~/.ssh/config
    Host internal-server
        HostName 10.0.0.50
        User admin
        ProxyJump bastion
    
    Host bastion
        HostName bastion.example.com
        User ubuntu
        IdentityFile ~/.ssh/id_ed25519

    SSH Hardening — cấu hình /etc/ssh/sshd_config

    Đây là phần quan trọng nhất cho SecOps. File cấu hình SSH server nằm tại /etc/ssh/sshd_config:

    # === CIS Benchmark SSH Hardening ===
    
    # Tắt login bằng root trực tiếp
    PermitRootLogin no
    
    # Chỉ dùng key, tắt password auth
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UsePAM yes
    
    # Chỉ cho phép user/group cụ thể
    AllowUsers deploy admin
    # AllowGroups sshusers
    
    # Port không phải 22 (security by obscurity, nhưng giảm noise)
    Port 2222
    
    # Giới hạn thời gian login
    LoginGraceTime 30
    MaxAuthTries 3
    MaxSessions 5
    
    # Disable các feature không cần
    X11Forwarding no
    AllowAgentForwarding no
    AllowTcpForwarding no   # Bật nếu cần port forward
    PermitTunnel no
    
    # Banner cảnh báo
    Banner /etc/issue.net
    
    # Protocol version (chỉ dùng SSH2)
    # Protocol 2  # Không cần thiết trên OpenSSH hiện đại, mặc định là 2
    
    # Logging
    LogLevel VERBOSE   # Log fingerprint của key khi login
    
    # Timeout inactive sessions
    ClientAliveInterval 300
    ClientAliveCountMax 2

    Sau khi sửa, test config trước khi restart:

    # Test config hợp lệ không
    sudo sshd -t
    
    # Restart SSH (giữ session hiện tại, chỉ áp dụng cho connection mới)
    sudo systemctl reload sshd

    Quan trọng: Trước khi tắt password auth, hãy đảm bảo đã copy public key lên server và test đăng nhập được bằng key. Nếu tắt password mà chưa có key, bạn sẽ bị lock out hoàn toàn.

    8. SSH Port Forwarding

    # Local port forwarding: truy cập service nội bộ qua tunnel
    # Truy cập PostgreSQL (port 5432) trên server qua local port 15432
    ssh -L 15432:localhost:5432 user@server
    
    # Kết nối local: psql -h localhost -p 15432
    
    # Remote port forwarding: expose local port ra ngoài qua server
    ssh -R 8080:localhost:3000 user@server
    
    # Dynamic port forwarding: SOCKS proxy
    ssh -D 1080 user@server
    # Dùng với browser hoặc proxychains

    9. Troubleshooting nhanh: Checklist kết nối

    Khi không kết nối được, làm theo thứ tự sau:

    1. Layer 1-2: ip link show — interface có UP không?
    2. Layer 3: ip addr show — có IP không? Đúng subnet không?
    3. Default gateway: ip route show — có default route không?
    4. Ping gateway: ping -c 3 [gateway_ip]
    5. Ping DNS: ping -c 3 8.8.8.8
    6. DNS resolution: dig google.com hoặc nslookup google.com
    7. Port có mở không: ss -tlnp | grep [port]
    8. Firewall: sudo ufw status hoặc sudo iptables -L -n
    9. Xem log: journalctl -u [service] --since "5 min ago"

    Tổng kết

    Bài này đã đi qua toàn bộ bộ công cụ networking thiết yếu trên Linux:

    • ip, ss: xem interface và connections đang chạy
    • ping, traceroute, dig: test connectivity và DNS
    • curl: tương tác với HTTP/HTTPS từ terminal
    • UFW, iptables: kiểm soát traffic vào/ra
    • tcpdump: bắt và phân tích packet
    • SSH hardening: bảo vệ điểm vào quan trọng nhất của server

    Từ góc nhìn SecOps, networking là nơi attacker thao túng nhiều nhất — từ reconnaissance bằng port scan, pivot qua mạng nội bộ, đến data exfiltration. Nắm vững các công cụ này giúp bạn vừa vận hành tốt, vừa phát hiện bất thường kịp thời.

    Bài tiếp theo chúng ta sẽ đi vào Package Management — cách cài phần mềm đúng cách, verify integrity và hiểu rủi ro supply chain trong môi trường Linux. Đây là chủ đề nóng trong bảo mật hiện đại khi các cuộc tấn công vào chuỗi cung ứng phần mềm ngày càng phổ biến.

  • Câu chuyện trước khi có Git

    Câu chuyện trước khi có Git

    Câu chuyện trước khi có Git

    Năm 2004. Một nhóm 3 lập trình viên đang làm dự án web cho khách hàng. Không có Git, không có version control. Họ dùng cách “truyền thống”: copy folder, đặt tên kiểu project_final, project_final_v2, project_FINAL_thật_sự, project_fix_bug_của_Tuấn

    Rồi một ngày, Minh sửa file checkout.php. Tuấn cũng sửa đúng file đó. Họ gửi cho nhau qua email. Ai merge? Merge bằng tay. Merge sai. Production sập. Khách hàng gọi điện lúc 11 giờ đêm.

    Câu chuyện này không phải hư cấu — đó là thực tế của hàng triệu team trước khi version control trở nên phổ biến. Và đó chính xác là vấn đề Git ra đời để giải quyết.


    Version Control System (VCS) là gì?

    VCS là hệ thống theo dõi mọi thay đổi trong codebase theo thời gian. Nó trả lời được 4 câu hỏi quan trọng:

    • Ai đã thay đổi file này?
    • Khi nào thay đổi xảy ra?
    • Thay đổi gì — thêm dòng nào, xóa dòng nào?
    • Tại sao — commit message giải thích lý do

    Với VCS, bạn có thể quay ngược thời gian. Bug xuất hiện từ tuần trước? Xem lịch sử, tìm commit nào gây ra, rollback. Team 10 người cùng sửa một file? Hệ thống tự merge, báo conflict chỗ nào cần giải tay.

    Các loại VCS

    Có 3 thế hệ:

    • Local VCS: Lưu lịch sử trên máy cá nhân. Đơn giản nhưng không cộng tác được. Ví dụ: RCS.
    • Centralized VCS (CVCS): Một server trung tâm lưu toàn bộ lịch sử. Mọi người kết nối vào đó. Ví dụ: SVN, CVS. Vấn đề: server chết = mọi người không làm việc được, mất server = mất toàn bộ lịch sử.
    • Distributed VCS (DVCS): Mỗi người có bản sao đầy đủ của repository — kể cả toàn bộ lịch sử. Không phụ thuộc server trung tâm. Git thuộc loại này.

    Git ra đời như thế nào?

    Git được tạo ra bởi Linus Torvalds — cha đẻ của Linux kernel — vào năm 2005. Câu chuyện khá thú vị:

    Trước đó, Linux kernel dùng một DVCS thương mại tên BitKeeper. Năm 2005, công ty làm BitKeeper thu hồi license miễn phí. Linus không vừa ý, quyết định tự viết một hệ thống mới. Ông đặt ra yêu cầu rõ ràng: phải nhanh, phải đơn giản, hỗ trợ phát triển phi tuyến tính (ngàn branch song song), hoàn toàn phân tán, và có thể handle dự án cỡ Linux kernel (hàng nghìn contributor).

    Ông viết Git trong… 10 ngày. Ngày 7/4/2005, Git tự host chính nó — repo đầu tiên của Git chứa source code của Git.


    Tại sao Git thống trị?

    Năm 2024, khảo sát Stack Overflow cho thấy 93.7% developer dùng Git. Đây không phải tình cờ. Git có một số đặc điểm khiến nó vượt trội:

    1. Branching cực nhanh và nhẹ

    Trong Git, tạo branch gần như tức thời — chỉ là tạo một pointer 40 bytes. Trong SVN, branch là copy toàn bộ directory. Sự khác biệt này thay đổi hoàn toàn workflow: với Git, bạn tạo branch cho mọi tính năng, mọi bugfix, thậm chí mọi thử nghiệm nhỏ.

    2. Làm việc offline hoàn toàn

    Vì mỗi máy có toàn bộ history, bạn commit, xem log, tạo branch, merge — tất cả đều được offline. Chỉ cần internet khi push/pull với server.

    3. Data integrity

    Mọi thứ trong Git được hash bằng SHA-1. Bạn không thể thay đổi lịch sử mà Git không biết. Mọi commit có fingerprint duy nhất. Điều này làm nền tảng cho audit trail trong môi trường DevSecOps.

    4. GitHub effect

    GitHub ra đời năm 2008 và biến Git từ công cụ của developer thành nền tảng cộng tác của cả thế giới. Open source, code review, CI/CD — tất cả xây trên Git.


    Git trong bức tranh DevOps/DevSecOps

    Nếu bạn đang học theo hướng DevOps hoặc DevSecOps, Git không chỉ là công cụ — nó là trung tâm của toàn bộ pipeline:

    Developer push code → Git repository
                               ↓
                        CI/CD trigger (GitHub Actions, GitLab CI, Jenkins)
                               ↓
                        Build → Test → Security Scan → Deploy
                               ↓
                        Production (với audit trail đầy đủ)
    

    Mọi thứ đều bắt đầu từ một git push. Hiểu Git = hiểu điểm khởi đầu của mọi automation trong DevOps.

    Với góc nhìn bảo mật, Git còn giúp:

    • Audit trail: ai thay đổi gì, khi nào — compliance requirement của nhiều tiêu chuẩn (SOC2, PCI-DSS)
    • Code review: mọi thay đổi đi qua Pull Request — không ai push thẳng vào production branch mà không có review
    • Secret detection: tool như git-secrets, TruffleHog scan commit trước khi push để không lộ API key
    • Signed commits: GPG sign commit để xác minh danh tính author

    Git vs GitHub vs GitLab — đừng nhầm lẫn

    Nhiều người mới hay lẫn lộn:

    Khái niệm Là gì Ví dụ
    Git Phần mềm VCS chạy trên máy bạn Cài bằng apt install git
    GitHub Dịch vụ web host Git repository, thuộc Microsoft github.com
    GitLab Tương tự GitHub, có thể self-host, tích hợp CI/CD mạnh hơn gitlab.com hoặc self-hosted
    Gitea Self-hosted Git server nhẹ, open source Dùng trong private infra

    Git là công cụ. GitHub/GitLab là nền tảng host và cộng tác xây trên Git. Bạn có thể dùng Git mà không cần GitHub — nhưng làm việc nhóm thực tế thì cần một nền tảng như vậy.


    Những lý do thực tế bạn cần học Git ngay

    Không phải lý thuyết — đây là những tình huống thực tế bạn sẽ gặp:

    1. Mọi job JD đều yêu cầu Git. Backend, frontend, DevOps, QA — tất cả đều cần. Không biết Git = thiếu kỹ năng nền tảng.
    2. Code review qua Pull Request. Đây là quy trình chuẩn tại mọi công ty làm phần mềm nghiêm túc. Không biết Git = không tham gia được.
    3. Deploy bằng git push. Heroku, Vercel, Railway, nhiều platform deploy khi bạn push code. Git = CD pipeline đơn giản nhất.
    4. Cứu code khi sự cố. Lỡ tay xóa file? Merge nhầm? Có Git, quay lại trạng thái trước trong 30 giây.
    5. Portfolio trên GitHub. Nhà tuyển dụng xem GitHub profile của bạn. Commit history đều đặn, project có README, code được review — đây là bằng chứng thực tế của năng lực.

    Bạn cần chuẩn bị gì để học series này?

    Series này thiết kế cho người mới hoàn toàn. Bạn chỉ cần:

    • Máy tính (Windows, macOS, hoặc Linux đều được)
    • Terminal/Command Prompt cơ bản — biết cd, ls, tạo file là đủ
    • Tài khoản GitHub miễn phí (tạo tại github.com)

    Không cần biết lập trình trước. Không cần kinh nghiệm với bất kỳ VCS nào khác. Chúng ta bắt đầu từ zero.


    Tổng kết

    Git là distributed version control system do Linus Torvalds tạo ra năm 2005. Nó giải quyết bài toán cộng tác, theo dõi lịch sử thay đổi, và bảo vệ code khỏi những tai nạn không mong muốn. Với DevOps/DevSecOps, Git là trung tâm của mọi pipeline — từ CI/CD đến audit trail và compliance.

    Học Git không phải là học thêm một tool. Đó là học cách làm việc chuyên nghiệp với code.

    Bài tiếp theo: Cài đặt & cấu hình Git lần đầu — chúng ta sẽ cài Git, setup tên/email, tạo SSH key và kết nối với GitHub để sẵn sàng cho mọi bài tiếp theo trong series.

  • Tại sao phải quan tâm đến process?

    Tại sao phải quan tâm đến process?

    Tại sao phải quan tâm đến process?

    Mỗi lần bạn chạy một lệnh, khởi động một dịch vụ, hay mở terminal — Linux tạo ra một process. Process là đơn vị thực thi cơ bản của hệ điều hành: nó có PID (Process ID) riêng, bộ nhớ riêng, quyền truy cập tài nguyên riêng.

    Với DevSecOps, việc hiểu process không chỉ để troubleshoot khi server chậm. Nó còn là kỹ năng cốt lõi của incident response: khi hệ thống bị xâm nhập, kẻ tấn công thường để lại dấu vết qua các process bất thường — reverse shell, cryptominer, hay backdoor ẩn mình sau tên tiến trình trông vô hại.

    Bài này sẽ đi từ nền tảng (process là gì, trạng thái, vòng đời) đến thực chiến (detect anomaly, monitor resource, trace system call).


    1. Process là gì? Vòng đời cơ bản

    Khi kernel chạy một chương trình, nó tạo ra một process với các thuộc tính:

    • PID: định danh duy nhất
    • PPID: PID của process cha (parent)
    • UID/GID: người dùng và nhóm sở hữu process
    • State: trạng thái hiện tại (running, sleeping, zombie…)
    • File descriptors: các file đang mở
    • Memory map: vùng bộ nhớ được cấp phát

    Trạng thái của process

    Ký hiệu Trạng thái Ý nghĩa
    R Running Đang thực thi hoặc trong run queue
    S Sleeping Đang chờ sự kiện (interruptible)
    D Uninterruptible sleep Chờ I/O, không thể kill — nguy hiểm nếu kéo dài
    T Stopped Bị tạm dừng bởi signal (Ctrl+Z)
    Z Zombie Đã kết thúc nhưng chưa được parent “gom” lại

    SecOps note: Trạng thái D kéo dài bất thường thường chỉ ra vấn đề I/O nghiêm trọng — có thể do ransomware đang encrypt disk, hoặc NFS mount bị treo.

    Zombie vs Orphan process

    Zombie process: process đã chết nhưng entry trong process table vẫn còn vì parent chưa gọi wait(). Nhìn thấy trạng thái Z trong ps. Thường không nguy hiểm nhưng nếu nhiều zombie → có thể là dấu hiệu parent process bị lỗi.

    Orphan process: process cha chết trước con. Kernel tự động reparent chúng về PID 1 (init/systemd). Bình thường, không đáng lo.


    2. ps — Snapshot tức thời

    ps là lệnh xem danh sách process đang chạy tại một thời điểm. Không real-time, chỉ là snapshot.

    # Xem tất cả process, format đầy đủ
    ps aux
    
    # Xem dạng cây (process hierarchy)
    ps auxf
    
    # Tìm process theo tên
    ps aux | grep nginx
    
    # Hiển thị cột cụ thể: PID, PPID, USER, command
    ps -eo pid,ppid,user,cmd --sort=-%cpu | head -20
    

    Giải mã output của ps aux:

    Cột Ý nghĩa
    USER Owner của process
    PID Process ID
    %CPU CPU usage tính từ lúc khởi động process
    %MEM Phần trăm RAM vật lý đang dùng
    VSZ Virtual memory size (KB)
    RSS Resident Set Size — RAM thực sự đang chiếm (KB)
    STAT Trạng thái process
    START Thời điểm khởi động
    COMMAND Lệnh đầy đủ

    SecOps tip: Kẻ tấn công hay đặt tên process giống tiến trình hợp lệ nhưng chạy từ path lạ. Kiểm tra:

    # Path thực sự của process (không chỉ tên)
    ps aux | awk '{print $11}' | sort -u
    
    # So sánh — /usr/sbin/sshd hợp lệ, còn /tmp/.hidden/sshd thì không
    

    3. tophtop — Monitoring real-time

    top

    top có sẵn trên mọi Linux, hiển thị real-time. Phần header chứa nhiều thông tin quan trọng:

    top - 14:32:01 up 42 days,  3:17,  2 users,  load average: 0.52, 0.48, 0.45
    Tasks: 214 total,   1 running, 213 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  5.2 us,  1.3 sy,  0.0 ni, 92.8 id,  0.5 wa,  0.0 hi,  0.2 si
    MiB Mem :  15886.5 total,   4231.2 free,   8742.1 used,   2913.2 buff/cache
    MiB Swap:   2048.0 total,   1987.6 free,     60.4 used.   6802.4 avail Mem
    

    Đọc load average: ba con số là trung bình 1 phút, 5 phút, 15 phút. Nếu load average > số CPU core — hệ thống đang quá tải. Nếu load tăng đột ngột trong khi không có workload mới → dấu hiệu đáng điều tra.

    Phím tắt hữu ích trong top:

    • P — sắp xếp theo CPU
    • M — sắp xếp theo Memory
    • k — kill process (nhập PID)
    • u — lọc theo user
    • 1 — xem từng CPU core riêng lẻ

    htop

    htop cần cài thêm (apt install htop) nhưng giao diện trực quan hơn nhiều: màu sắc, cây tiến trình, dễ dùng chuột. Dùng F9 để send signal, F5 để xem dạng cây.

    sudo apt install htop   # Ubuntu/Debian
    sudo dnf install htop   # Rocky/RHEL
    

    4. Signals — Giao tiếp với process

    Signal là cơ chế kernel dùng để thông báo cho process. Phổ biến nhất:

    Signal Số Ý nghĩa
    SIGHUP 1 Reload config (không restart)
    SIGINT 2 Interrupt (Ctrl+C)
    SIGTERM 15 Yêu cầu thoát gracefully — mặc định của kill
    SIGKILL 9 Buộc kill ngay, không thể block hay ignore
    SIGSTOP 19 Pause process (không thể block)
    # Gửi SIGTERM (graceful shutdown)
    kill 1234
    kill -15 1234
    
    # Buộc kill khi process không phản hồi
    kill -9 1234
    
    # Kill theo tên
    killall nginx
    pkill -f "python app.py"
    
    # Reload config nginx (dùng SIGHUP)
    kill -HUP $(cat /var/run/nginx.pid)
    

    Best practice: Luôn thử SIGTERM trước. SIGKILL là lựa chọn cuối cùng — nó không cho process dọn dẹp, có thể gây data corruption hoặc bỏ qua cleanup routine quan trọng.


    5. nicerenice — Ưu tiên process

    Linux scheduler phân bổ CPU dựa trên priority. nice value dao động từ -20 (ưu tiên cao nhất) đến 19 (ưu tiên thấp nhất). Mặc định là 0.

    # Chạy process với nice thấp (ít ăn CPU)
    nice -n 10 ./heavy-script.sh
    
    # Thay đổi priority của process đang chạy
    renice -n 5 -p 1234
    
    # Chỉ root mới có thể set nice âm (tăng priority)
    sudo renice -n -5 -p 1234
    

    Dùng nice khi chạy backup, compression hay các job nặng trong giờ cao điểm — tránh ảnh hưởng đến dịch vụ production.


    6. /proc filesystem — Nhìn vào não hệ thống

    /proc là virtual filesystem — không chiếm disk thực, tồn tại trong RAM. Kernel expose thông tin nội bộ qua đây.

    # Thông tin process PID 1234
    ls /proc/1234/
    
    # Lệnh đầy đủ (bao gồm argument)
    cat /proc/1234/cmdline | tr '' ' '
    
    # File đang mở
    cat /proc/1234/fd/
    
    # Memory maps
    cat /proc/1234/maps
    
    # Môi trường biến của process
    cat /proc/1234/environ | tr '' 'n'
    

    Một số file system-wide quan trọng trong /proc:

    • /proc/cpuinfo — thông tin CPU
    • /proc/meminfo — thông tin RAM chi tiết
    • /proc/net/tcp — connections TCP hiện tại (raw format)
    • /proc/sys/ — kernel parameters có thể điều chỉnh qua sysctl
    • /proc/loadavg — load average hiện tại

    SecOps application: Khi cần forensics một process đáng ngờ:

    PID=1337
    
    # Lệnh gốc (quan trọng — kẻ tấn công có thể rename process nhưng cmdline không đổi)
    cat /proc/$PID/cmdline | tr '' ' '
    
    # Executable thực sự trỏ về đâu?
    ls -la /proc/$PID/exe
    
    # Network connections của process này
    cat /proc/$PID/net/tcp
    
    # Biến môi trường (có thể chứa API key, credential bị leak)
    cat /proc/$PID/environ | tr '' 'n'
    

    7. Resource monitoring — free, vmstat, iostat

    free — Memory

    free -h
    
                  total        used        free      shared  buff/cache   available
    Mem:           15Gi        8.5Gi       4.2Gi       512Mi       2.8Gi       6.8Gi
    Swap:          2.0Gi       60Mi        1.9Gi
    

    Cột available quan trọng hơn free — nó bao gồm cả buff/cache có thể giải phóng ngay khi cần. Nếu available xuống gần 0 và swap đang dùng nhiều → hệ thống đang thrashing, performance tụt nghiêm trọng.

    vmstat — Virtual Memory & I/O

    # Xem mỗi 2 giây, 5 lần
    vmstat 2 5
    

    Chú ý cột wa (I/O wait) — nếu cao liên tục → disk I/O là bottleneck. Cột si/so (swap in/out) tăng → dấu hiệu thiếu RAM.

    iostat — Disk I/O

    sudo apt install sysstat
    iostat -x 2 5
    

    Chỉ số %util gần 100% nghĩa là disk đang bão hòa. await cao (> vài chục ms với SSD) → latency I/O bất thường.


    8. lsof — List Open Files

    Mọi thứ trong Linux đều là file — kể cả socket mạng. lsof cho bạn thấy file nào đang mở bởi process nào.

    # File đang mở bởi process có PID 1234
    lsof -p 1234
    
    # Process đang mở file/directory cụ thể
    lsof /var/log/syslog
    
    # Network connections (thay thế netstat trên nhiều distro mới)
    lsof -i
    
    # Connections đến port 80
    lsof -i :80
    
    # Connections của user cụ thể
    lsof -u www-data
    
    # File đã bị xóa nhưng vẫn đang được giữ mở (chiếm disk)
    lsof | grep deleted
    

    SecOps use case: Tìm process đang listen trên port lạ:

    lsof -i -P -n | grep LISTEN
    # -P: hiển thị số port thay vì service name
    # -n: không resolve hostname (nhanh hơn)
    

    9. strace — Theo dõi system calls

    strace trace mọi system call mà process thực hiện — đọc file, gọi mạng, cấp phát memory… Đây là công cụ debug và forensics cực kỳ mạnh.

    # Trace process đang chạy
    strace -p 1234
    
    # Trace lệnh mới
    strace ls /tmp
    
    # Chỉ trace system calls cụ thể
    strace -e openat,read,write cat /etc/passwd
    
    # Tóm tắt (đếm số lần gọi)
    strace -c ls /tmp
    
    # Trace cả child processes
    strace -f -p 1234
    
    # Lưu output ra file (thường rất nhiều)
    strace -p 1234 -o /tmp/trace.log
    

    SecOps application: Nếu nghi ngờ process đang đọc file nhạy cảm hay gửi data ra ngoài:

    # Xem process có đọc file gì
    strace -e openat,open -p $SUSPICIOUS_PID 2>&1 | grep -v "ENOENT"
    
    # Xem network syscalls
    strace -e connect,sendto,recvfrom -p $SUSPICIOUS_PID
    

    Lưu ý: strace làm chậm process đáng kể — không dùng trên production traffic cao, chỉ dùng khi debug hoặc incident investigation.


    10. uptime và who — Quick sanity check

    # Thời gian chạy và load average
    uptime
    
    # Ai đang logged in
    who
    w
    
    # Last login history
    last
    last -n 20   # 20 dòng gần nhất
    
    # Failed login attempts
    sudo lastb
    

    lastlastb là hai lệnh đầu tiên nên chạy khi điều tra xâm nhập — xem có login bất thường từ IP lạ hay giờ lạ không.


    Tổng kết

    Process monitoring là kỹ năng nền tảng của cả sysadmin lẫn security engineer. Nắm được vài điểm cốt lõi:

    • ps aux / htop: snapshot và real-time view của mọi process
    • Signals: SIGTERM trước, SIGKILL chỉ khi cần thiết
    • /proc/[pid]/: nguồn thông tin chi tiết nhất về bất kỳ process nào
    • lsof: file và network socket đang mở
    • strace: vũ khí cuối cùng khi cần biết process thực sự đang làm gì

    Với DevSecOps, bộ kỹ năng này trực tiếp phục vụ incident response: phát hiện cryptominer, reverse shell, hay malware ẩn náu trong hệ thống. Đây không phải lý thuyết — đây là thứ bạn cần khi 3 giờ sáng nhận alert và phải tìm ra kẻ xâm nhập trong 15 phút.

    Bài tiếp theo: Networking cơ bản — chúng ta sẽ nói về cách kiểm tra, cấu hình và bảo vệ kết nối mạng trên Linux, từ ip, ss, đến SSH hardening và tcpdump để bắt gói tin ngay trên server.

  • Tại sao Permissions lại quan trọng đến vậy?

    Tại sao Permissions lại quan trọng đến vậy?

    Tại sao Permissions lại quan trọng đến vậy?

    Hầu hết các vụ leo thang đặc quyền (privilege escalation) trên Linux đều bắt nguồn từ một nguyên nhân đơn giản: permission được cấu hình sai. Một file có SUID bit bật nhầm, một thư mục /tmp không có Sticky bit, một user được cấp sudo quá rộng — đó là những cái bẫy mà cả sysadmin lẫn developer thường vô tình giăng ra cho chính mình.

    Bài này sẽ đi từ gốc rễ: mô hình phân quyền của Linux, cách quản lý user/group, rồi đến các “vũ khí” nâng cao như SUID/SGID/Sticky bit — những thứ mà bất kỳ ai học DevSecOps đều phải nắm chắc.

    Mô hình phân quyền Linux: rwx

    Linux dùng mô hình phân quyền dựa trên 3 đối tượng và 3 loại quyền:

    3 đối tượng (who)

    • Owner (u) — người sở hữu file
    • Group (g) — nhóm được gán cho file
    • Others (o) — tất cả người dùng còn lại

    3 loại quyền (what)

    • r (read) — đọc file / liệt kê nội dung thư mục
    • w (write) — ghi/sửa file / tạo-xóa file trong thư mục
    • x (execute) — chạy file / truy cập vào thư mục

    Khi chạy ls -l, bạn sẽ thấy output dạng:

    -rwxr-xr--  1 alice  devops  4096 May 27 20:00 deploy.sh
    

    Đọc từng phần:

    Ký tự Ý nghĩa
    - Loại: file thường (d=thư mục, l=symlink)
    rwx Owner (alice): đọc, ghi, chạy
    r-x Group (devops): đọc, chạy — không ghi
    r-- Others: chỉ đọc

    chmod — Thay đổi quyền

    Có 2 cú pháp: symbolic và octal. Dân thực chiến dùng cả hai tùy ngữ cảnh.

    Symbolic mode

    # Thêm quyền execute cho owner
    chmod u+x script.sh
    
    # Bỏ quyền write của others
    chmod o-w config.yaml
    
    # Gán chính xác quyền cho group
    chmod g=rx deploy.sh
    
    # Áp dụng cho tất cả (a = all: u+g+o)
    chmod a+r README.md
    

    Octal mode

    Mỗi quyền là một bit: r=4, w=2, x=1. Cộng lại cho từng nhóm:

    Octal Binary Permissions
    7 111 rwx
    6 110 rw-
    5 101 r-x
    4 100 r–
    0 000
    # 755: owner=rwx, group=r-x, others=r-x (chuẩn cho script)
    chmod 755 deploy.sh
    
    # 600: chỉ owner đọc/ghi (chuẩn cho private key SSH)
    chmod 600 ~/.ssh/id_rsa
    
    # 644: owner đọc/ghi, others chỉ đọc (chuẩn cho config file)
    chmod 644 /etc/nginx/nginx.conf
    
    # Recursive: áp dụng cho cả thư mục
    chmod -R 750 /var/app/
    

    SecOps note: Dùng find để phát hiện file có quyền quá rộng:

    # Tìm file world-writable (anyone can write — nguy hiểm!)
    find / -type f -perm -o+w 2>/dev/null
    
    # Tìm thư mục world-writable
    find / -type d -perm -o+w 2>/dev/null
    

    chown & chgrp — Thay đổi sở hữu

    # Đổi owner
    chown alice file.txt
    
    # Đổi cả owner lẫn group
    chown alice:devops file.txt
    
    # Chỉ đổi group
    chgrp devops file.txt
    
    # Recursive
    chown -R www-data:www-data /var/www/html/
    

    Nguyên tắc vàng: mỗi service chạy với user riêng, chỉ có quyền đọc/ghi đúng thư mục nó cần. Nginx chạy với user www-data, không cần và không nên có quyền ra ngoài /var/www/.

    Users & Groups: Quản lý danh tính trên Linux

    Các file quan trọng

    # Thông tin user (không có password hash)
    cat /etc/passwd
    # Format: username:x:UID:GID:comment:home:shell
    # root:x:0:0:root:/root:/bin/bash
    # www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
    
    # Password hash (chỉ root đọc được)
    cat /etc/shadow
    # alice:$6$rounds=4096$salt$hash...:19500:0:99999:7:::
    
    # Danh sách group
    cat /etc/group
    # Format: groupname:x:GID:members
    # devops:x:1001:alice,bob
    

    SecOps note: File /etc/shadow phải có permission 640 hoặc 000, chỉ root hoặc group shadow được đọc. Nếu file này readable bởi others — đó là một lỗ hổng nghiêm trọng.

    Quản lý user

    # Tạo user mới với home directory
    useradd -m -s /bin/bash alice
    
    # Tạo service account (không cần login)
    useradd -r -s /usr/sbin/nologin -d /var/lib/myapp myapp
    
    # Đặt password
    passwd alice
    
    # Sửa thông tin user
    usermod -aG devops alice   # Thêm alice vào group devops
    usermod -L alice           # Lock account
    usermod -U alice           # Unlock account
    
    # Xóa user (và home directory)
    userdel -r alice
    

    Quản lý group

    # Tạo group
    groupadd devops
    
    # Xem user thuộc group nào
    groups alice
    id alice
    
    # Xem thành viên của group
    getent group devops
    

    UID/GID đặc biệt

    Range Loại
    0 root — toàn quyền hệ thống
    1–999 System accounts (daemon, service users)
    1000+ Regular users

    sudo: Ủy quyền có kiểm soát

    sudo cho phép user thường chạy lệnh với quyền root (hoặc user khác) mà không cần biết password của root. Toàn bộ cấu hình nằm trong /etc/sudoerschỉ sửa bằng visudo, không bao giờ dùng text editor thường vì một lỗi cú pháp có thể khóa hệ thống.

    # Mở sudoers an toàn
    visudo
    

    Cú pháp sudoers

    # Cho alice toàn quyền sudo (giống root)
    alice ALL=(ALL:ALL) ALL
    
    # Cho alice chạy một số lệnh cụ thể không cần password
    alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/journalctl
    
    # Cho group devops sudo
    %devops ALL=(ALL) ALL
    
    # Xấu: cho phép chạy bất kỳ lệnh nào bằng NOPASSWD
    alice ALL=(ALL) NOPASSWD: ALL  # <-- đừng làm vậy!
    

    Thực hành tốt với sudo:

    • Chỉ cấp quyền sudo cho đúng lệnh cần thiết (least privilege)
    • Tránh NOPASSWD: ALL — nếu session bị chiếm, kẻ tấn công có ngay toàn quyền
    • Log sudo được ghi vào /var/log/auth.log (Ubuntu) hoặc /var/log/secure (RHEL) — đây là nguồn audit quan trọng
    # Xem lịch sử sudo
    grep sudo /var/log/auth.log | tail -20
    

    su vs sudo

    su sudo
    Xác thực Password của target user Password của chính bạn
    Audit trail Yếu — chỉ biết ai switch Mạnh — ghi từng lệnh
    Granularity Toàn bộ session Từng lệnh cụ thể
    Khuyến nghị Hạn chế dùng Ưu tiên dùng

    SUID, SGID và Sticky Bit: Những bit đặc biệt

    Ngoài rwx, Linux còn có 3 bit đặc biệt — đây cũng là nơi nhiều lỗ hổng bảo mật ẩn nấp nhất.

    SUID (Set User ID) — bit s trên owner

    Khi SUID được bật trên một executable, file đó chạy với quyền của owner, không phải người đang chạy nó.

    # Ví dụ điển hình: /usr/bin/passwd
    ls -l /usr/bin/passwd
    # -rwsr-xr-x 1 root root 68208 /usr/bin/passwd
    #     ^-- chữ 's' thay cho 'x' của owner = SUID
    

    Lý do passwd cần SUID: nó phải ghi vào /etc/shadow (chỉ root mới ghi được), nhưng bất kỳ user nào cũng cần chạy được lệnh đổi password của họ.

    # Bật SUID
    chmod u+s /path/to/program
    # hoặc octal: 4755
    
    # Tìm tất cả file SUID trên hệ thống (SecOps audit!)
    find / -perm -4000 -type f 2>/dev/null
    

    ⚠️ SecOps alert: Bất kỳ binary nào có SUID + owned by root đều là mục tiêu của kẻ tấn công. Nếu binary đó có lỗ hổng (ví dụ: buffer overflow), khai thác nó = leo thang lên root. Đây là kỹ thuật SUID exploitation cơ bản trong CTF lẫn pentest thực tế.

    SGID (Set Group ID) — bit s trên group

    Trên file executable: chạy với quyền của group sở hữu file.
    Trên thư mục: file tạo trong thư mục sẽ kế thừa group của thư mục — rất hữu ích cho shared directories.

    # Bật SGID trên thư mục dùng chung
    chmod g+s /var/shared/team/
    # hoặc octal: 2755
    
    ls -ld /var/shared/team/
    # drwxr-sr-x 2 root devops 4096 /var/shared/team/
    #        ^-- 's' ở vị trí group execute = SGID
    
    # Tìm file SGID
    find / -perm -2000 -type f 2>/dev/null
    

    Sticky Bit — bit t trên others

    Khi Sticky bit được bật trên thư mục: chỉ owner của file mới có thể xóa file đó, dù thư mục có permission write cho all.

    ls -ld /tmp
    # drwxrwxrwt 10 root root 4096 /tmp
    #          ^-- chữ 't' = Sticky bit
    
    # Bật Sticky bit
    chmod +t /var/shared/uploads/
    # hoặc octal: 1777
    

    Nếu /tmp không có Sticky bit — bất kỳ user nào cũng có thể xóa file của user khác trong /tmp. Đó là lý do Sticky bit là mặc định bắt buộc trên thư mục /tmp của mọi distro Linux.

    Tóm tắt 3 bit đặc biệt

    Bit Octal Trên file Trên thư mục
    SUID 4000 Chạy với UID của owner Không có tác dụng (trên Linux)
    SGID 2000 Chạy với GID của group File mới kế thừa group
    Sticky 1000 Không có tác dụng Chỉ owner mới xóa được file của mình

    umask — Quyền mặc định khi tạo file

    umask xác định quyền bị trừ đi khi tạo file/thư mục mới. Mặc định thường là 022:

    umask
    # 0022
    
    # File mới: 666 - 022 = 644 (rw-r--r--)
    # Thư mục mới: 777 - 022 = 755 (rwxr-xr-x)
    
    # Đổi umask cho session hiện tại
    umask 027
    # File mới: 666 - 027 = 640 (chặt hơn: group chỉ đọc, others không gì)
    

    Để đặt umask cố định, thêm vào /etc/profile hoặc /etc/bash.bashrc. Nhiều tổ chức yêu cầu umask 027 hoặc 077 cho môi trường production.

    Checklist audit nhanh — Permission hardening

    # 1. File SUID/SGID (review từng cái)
    find / -perm /6000 -type f 2>/dev/null | sort
    
    # 2. File world-writable (ai cũng ghi được)
    find / -perm -o+w -not -path "/proc/*" -type f 2>/dev/null
    
    # 3. /etc/shadow permission
    stat /etc/shadow | grep Access
    
    # 4. Thư mục home có sticky bit chưa
    ls -ld /home/*
    
    # 5. User có shell login nhưng không cần thiết
    grep -v nologin /etc/passwd | grep -v "false"
    
    # 6. Ai đang có quyền sudo?
    grep -E '^[^#]' /etc/sudoers /etc/sudoers.d/* 2>/dev/null
    getent group sudo wheel
    

    Tổng kết

    Phân quyền Linux xây dựng trên nền tảng đơn giản — ba đối tượng, ba quyền — nhưng sức mạnh thực sự nằm ở cách kết hợp chúng: cấp đúng quyền, cho đúng người, trong đúng ngữ cảnh. Nguyên tắc least privilege không phải khái niệm trừu tượng mà là việc bạn làm mỗi ngày: chmod 600 cho private key, tạo service account với nologin, viết sudoers chỉ cấp lệnh cần thiết.

    SUID/SGID/Sticky bit là lớp nâng cao cần hiểu đúng — dùng sai một bit là để lộ một cửa hậu không ai ngờ tới. Audit định kỳ bằng find -perm là thói quen bắt buộc của bất kỳ SecOps engineer nào.

    Bài tiếp theo, chúng ta sẽ lên tầng trên: Processes & System Monitoring — học cách quan sát những gì đang chạy trên hệ thống, phân biệt process bình thường với process đáng ngờ, và dùng ps, top, lsof, strace như một incident responder thực thụ.

  • FHS — Tiêu chuẩn cấu trúc thư mục

    FHS — Tiêu chuẩn cấu trúc thư mục

    Mở terminal lần đầu, nhiều người gõ cd / rồi ls — và thấy một rừng thư mục lạ: bin, etc, proc, sys, var… Không giống Windows chút nào. Không có ổ C hay ổ D. Tất cả nằm chung trong một cây thư mục duy nhất bắt đầu từ /.

    Đây không phải ngẫu nhiên. Mỗi thư mục trong Linux tồn tại vì một lý do cụ thể, được chuẩn hóa bởi Filesystem Hierarchy Standard (FHS). Hiểu được bản đồ này, bạn sẽ biết ngay file config nằm ở đâu, log được lưu chỗ nào, và tại sao /proc lại là công cụ troubleshooting mạnh nhất trên Linux.

    FHS — Tiêu chuẩn cấu trúc thư mục

    FHS là thỏa thuận chung giữa các distro Linux: dù bạn dùng Ubuntu, Debian, Rocky hay Arch, cấu trúc thư mục đều tuân theo cùng một quy ước. Điều này có nghĩa là kỹ năng navigate trên Ubuntu hoạt động ngay trên server Rocky Linux của production.

    Toàn bộ filesystem bắt đầu từ root directory, ký hiệu là / (dấu gạch chéo). Không nhầm với /root — đó là home directory của user root. / là gốc của toàn bộ cây thư mục.

    Bản đồ các thư mục quan trọng

    /etc — Trái tim cấu hình hệ thống

    /etc chứa toàn bộ file cấu hình của hệ thống và các ứng dụng. Tên viết tắt từ “Editable Text Configuration” (theo quy ước hiện đại). Đây là thư mục bạn sẽ vào nhiều nhất khi quản trị server.

    /etc/
    ├── passwd          # Danh sách user (không chứa password thật)
    ├── shadow          # Password hash (chỉ root đọc được)
    ├── group           # Danh sách group
    ├── sudoers         # Ai được quyền sudo gì
    ├── hostname        # Tên máy
    ├── hosts           # DNS tĩnh (map domain → IP)
    ├── resolv.conf     # DNS server
    ├── fstab           # Cấu hình mount point tự động khi boot
    ├── crontab         # Scheduled tasks hệ thống
    ├── ssh/
    │   └── sshd_config # Cấu hình SSH server
    ├── nginx/          # Cấu hình Nginx
    └── systemd/        # Unit files của systemd

    Quy tắc vàng: Trước khi sửa bất kỳ file nào trong /etc, backup trước:

    $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

    /var — Dữ liệu thay đổi liên tục

    /var (variable) chứa dữ liệu thay đổi thường xuyên trong quá trình hệ thống chạy: log, cache, database, mail queue, lock file.

    /var/
    ├── log/            # Log hệ thống và ứng dụng
    │   ├── syslog      # Log chính (Ubuntu/Debian)
    │   ├── messages    # Log chính (RHEL/Rocky)
    │   ├── auth.log    # Đăng nhập, sudo, SSH
    │   ├── kern.log    # Kernel messages
    │   └── nginx/      # Access/error log của Nginx
    ├── www/            # Web root (thường đặt website ở đây)
    ├── lib/            # State data của ứng dụng
    ├── cache/          # Cache của các package manager
    ├── spool/          # Print queue, mail queue
    └── run/            # PID files, socket files

    Trong DevSecOps, /var/log là nơi đầu tiên bạn kiểm tra khi có sự cố. Bài 8 của series này sẽ đi sâu vào log management.

    /proc — Cửa sổ vào kernel đang chạy

    /proc là một virtual filesystem — không tồn tại trên ổ đĩa. Kernel tạo ra nó trong RAM và cập nhật real-time. Mỗi process đang chạy có một thư mục con trong /proc với tên là PID của nó.

    # Xem thông tin CPU
    $ cat /proc/cpuinfo
    
    # Xem RAM
    $ cat /proc/meminfo
    
    # Xem uptime hệ thống
    $ cat /proc/uptime
    
    # Xem tất cả process đang chạy
    $ ls /proc | grep -E '^[0-9]+$'
    
    # Xem chi tiết process PID 1234
    $ ls /proc/1234/
    $ cat /proc/1234/cmdline   # Lệnh đã chạy process này
    $ cat /proc/1234/status    # Trạng thái: CPU, RAM, state
    $ ls -la /proc/1234/fd/    # File descriptors đang mở

    Ứng dụng thực tế: Khi điều tra incident, /proc/[pid]/ cho bạn biết một process đang làm gì, mở file nào, kết nối tới đâu — mà không cần cài thêm tool nào.

    /sys — Giao tiếp với hardware và kernel

    /sys (sysfs) cũng là virtual filesystem, nhưng thay vì thông tin process, nó expose cấu hình kernel và hardware. Bạn có thể đọc và ghi vào đây để thay đổi hành vi kernel mà không cần reboot.

    # Xem danh sách network interface
    $ ls /sys/class/net/
    
    # Xem tốc độ link của eth0
    $ cat /sys/class/net/eth0/speed
    
    # Bật/tắt IPv6 (không cần reboot)
    $ echo 1 | sudo tee /sys/net/ipv6/conf/all/disable_ipv6
    
    # Xem thông tin battery (laptop)
    $ cat /sys/class/power_supply/BAT0/capacity

    Trong bài Hardening (Bài 9), bạn sẽ dùng /etc/sysctl.conf để thay đổi kernel parameters một cách persistent thông qua /proc/sys.

    /tmp — Bãi rác tạm thời

    /tmp chứa file tạm thời, bị xóa khi reboot (hoặc theo policy của distro). Bất kỳ user nào cũng có thể ghi vào đây.

    # Tạo file tạm để test
    $ echo "test" > /tmp/mytest.txt
    
    # Xem policy xóa tự động
    $ cat /usr/lib/tmpfiles.d/tmp.conf

    ⚠️ Lưu ý bảo mật: /tmp là target phổ biến của malware và khai thác privilege escalation. Trong hardening, người ta thường mount /tmp với flag noexec để ngăn chạy binary từ đây.

    Các thư mục quan trọng khác

    /bin   → Binaries cơ bản (ls, cp, mv...) — link tới /usr/bin trên distro mới
    /sbin  → System binaries (fdisk, ifconfig...) — chỉ root dùng
    /usr   → User programs: /usr/bin, /usr/lib, /usr/share
    /home  → Home directory của các user (/home/richard, /home/deploy)
    /root  → Home directory của root user
    /boot  → Kernel và bootloader (GRUB)
    /dev   → Device files (ổ đĩa, terminal, random...)
    /opt   → Software cài thêm từ bên ngoài (không qua package manager)
    /mnt   → Mount point tạm thời
    /media → Mount point cho USB, CD-ROM
    /lib   → Shared libraries (.so files)

    Đường dẫn tuyệt đối vs tương đối

    Đây là khái niệm quan trọng nhất khi làm việc với filesystem:

    Đường dẫn tuyệt đối bắt đầu từ / — luôn chính xác dù bạn đang đứng ở đâu:

    $ cat /etc/nginx/nginx.conf      # Luôn tìm đúng file này
    $ cd /var/log                    # Luôn vào đúng thư mục này

    Đường dẫn tương đối tính từ thư mục hiện tại — ngắn hơn nhưng phụ thuộc vào vị trí bạn đang đứng:

    # Đang đứng ở /var
    $ cat log/nginx/access.log       # = /var/log/nginx/access.log
    $ cd ..                          # Lên /
    $ cd ../home/richard             # Từ /var lên / rồi vào /home/richard
    
    # Ký hiệu đặc biệt:
    # .   = thư mục hiện tại
    # ..  = thư mục cha
    # ~   = home directory của user hiện tại

    Mẹo thực chiến: Trong script, luôn dùng đường dẫn tuyệt đối để tránh bug khi script chạy từ thư mục khác.

    Các lệnh navigate cần biết

    # pwd — biết mình đang ở đâu
    $ pwd
    /home/richard
    
    # ls — liệt kê nội dung
    $ ls -la /etc/ssh
    
    # cd — di chuyển
    $ cd /var/log
    $ cd ..           # lên /var
    $ cd -            # quay lại /var/log (như nút Back)
    $ cd ~            # về home
    
    # tree — xem cây thư mục (cần cài: apt install tree)
    $ tree /etc/nginx
    $ tree -L 2 /var  # chỉ 2 cấp sâu
    
    # find — tìm file theo điều kiện
    $ find /etc -name "*.conf"              # tìm file .conf
    $ find /var/log -mtime -1              # sửa trong 24h qua
    $ find /home -type d -name ".ssh"      # tìm thư mục .ssh
    $ find / -perm -4000 2>/dev/null       # tìm file SUID (quan trọng cho SecOps)
    
    # locate — tìm nhanh qua database index
    $ sudo updatedb                        # cập nhật database
    $ locate sshd_config                   # tìm ngay lập tức

    find vs locate: find tìm real-time trên ổ đĩa — chậm hơn nhưng luôn chính xác. locate tìm qua database được index trước — rất nhanh nhưng có thể cũ nếu chưa updatedb.

    Đây là phần nhiều người bỏ qua nhưng lại xuất hiện thường xuyên khi debug hoặc thiết kế hệ thống.

    Inode là gì?

    Mỗi file trên Linux thực ra gồm hai phần tách biệt:

    1. Inode — metadata của file: kích thước, quyền, timestamps, con trỏ đến vị trí data trên ổ đĩa. Không chứa tên file.
    2. Directory entry — ánh xạ giữa tên file và inode number.
    # Xem inode number của file
    $ ls -li /etc/hosts
    131073 -rw-r--r-- 1 root root 221 May 10 09:00 /etc/hosts
    # 131073 là inode number
    
    # Xem thông tin inode chi tiết
    $ stat /etc/hosts
      File: /etc/hosts
      Size: 221
      Inode: 131073
      Links: 1
      Access: (0644/-rw-r--r--)
      Modify: 2026-05-10 09:00:00

    Hard link là một tên file khác trỏ vào cùng một inode. Không tốn thêm dung lượng, không phân biệt “original” hay “link”:

    # Tạo hard link
    $ ln /etc/hosts /tmp/hosts-hardlink
    
    # Cả hai trỏ vào cùng inode
    $ ls -li /etc/hosts /tmp/hosts-hardlink
    131073 -rw-r--r-- 2 root root 221 ... /etc/hosts
    131073 -rw-r--r-- 2 root root 221 ... /tmp/hosts-hardlink
    # Cùng inode 131073, Links count = 2
    
    # Xóa một cái, file vẫn tồn tại qua cái kia
    $ rm /tmp/hosts-hardlink
    $ cat /etc/hosts   # Vẫn đọc được

    Giới hạn của hard link: Không thể tạo hard link xuyên filesystem, không thể hard link thư mục.

    Symlink là file đặc biệt chứa đường dẫn đến file/thư mục khác — giống shortcut trên Windows. Có inode riêng.

    # Tạo symlink (-s = symbolic)
    $ ln -s /etc/nginx/nginx.conf ~/nginx.conf
    
    # Xem symlink
    $ ls -la ~/nginx.conf
    lrwxrwxrwx 1 richard richard 22 ... nginx.conf -> /etc/nginx/nginx.conf
    # Dấu l ở đầu = symlink, -> chỉ đến đích
    
    # Symlink có thể trỏ đến thư mục
    $ ln -s /var/log/nginx ~/logs
    
    # Kiểm tra symlink còn valid không
    $ readlink -f ~/nginx.conf

    Symlink bị “broken” khi file gốc bị xóa hoặc di chuyển — lúc này symlink vẫn tồn tại nhưng trỏ vào khoảng không.

    Dùng khi nào?

    • Hard link: Backup, deduplication, khi cần đảm bảo data tồn tại dù một đường dẫn bị xóa.
    • Symlink: Mọi trường hợp còn lại — config, deploy, version switching.
    # Pattern phổ biến trong deploy: dùng symlink để switch version
    $ ls -la /var/www/
    myapp-v1.2.0/    # thư mục thật
    myapp-v1.3.0/    # thư mục thật
    current -> myapp-v1.3.0/   # symlink — Nginx trỏ vào đây
    
    # Deploy version mới: chỉ cần đổi symlink, không downtime
    $ ln -sfn /var/www/myapp-v1.4.0 /var/www/current

    Mount Points — Filesystem trong Filesystem

    Trên Linux, mọi thiết bị lưu trữ đều được “gắn” vào một điểm trong cây thư mục. Đây gọi là mount point. Ổ đĩa thứ hai không xuất hiện như ổ D — nó được mount vào /data hoặc /mnt/disk2.

    # Xem tất cả filesystem đang được mount
    $ mount | column -t
    
    # Xem dạng gọn hơn
    $ df -hT
    Filesystem     Type      Size  Used Avail Use% Mounted on
    /dev/sda1      ext4       50G   12G   36G  25% /
    /dev/sda2      ext4      200G   80G  108G  43% /data
    tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
    
    # Xem mount points dạng cây
    $ findmnt

    /etc/fstab — Mount tự động khi boot

    File /etc/fstab định nghĩa filesystem nào được mount tự động mỗi khi boot:

    $ cat /etc/fstab
    # <device>    <mount point>  <type>  <options>        <dump> <pass>
    UUID=abc123   /              ext4    defaults           0      1
    UUID=def456   /data          ext4    defaults,noatime   0      2
    UUID=ghi789   /boot          ext4    defaults           0      2
    tmpfs         /tmp           tmpfs   nodev,nosuid,noexec 0     0

    Chú ý cột optionsnodev,nosuid,noexec trên /tmp là hardening cơ bản: không cho phép device file, SUID, và chạy binary từ /tmp.

    # Mount thủ công (tạm thời, không lưu qua reboot)
    $ sudo mount /dev/sdb1 /mnt/usb
    
    # Unmount
    $ sudo umount /mnt/usb
    
    # Mount theo fstab (chỉ cần ghi /mnt/data nếu đã có trong fstab)
    $ sudo mount /mnt/data

    /proc và /sys trong troubleshooting thực tế

    Đây là lý do tại sao hiểu filesystem quan trọng với DevSecOps — bạn có thể debug mà không cần cài thêm tool:

    # Server chậm? Xem load average real-time
    $ watch -n 1 cat /proc/loadavg
    
    # Tìm process đang mở quá nhiều file (potential file descriptor leak)
    $ ls /proc/*/fd | wc -l
    
    # Xem network connections của process PID 1234
    $ cat /proc/1234/net/tcp
    
    # Kiểm tra kernel parameters bảo mật
    $ cat /proc/sys/net/ipv4/ip_forward         # IP forwarding
    $ cat /proc/sys/kernel/randomize_va_space   # ASLR
    
    # Xem memory map của process (useful khi phân tích malware)
    $ cat /proc/1234/maps
    
    # Detect process đang chạy từ /tmp (dấu hiệu xấu)
    $ ls -la /proc/*/exe 2>/dev/null | grep tmp

    Tổng kết

    Filesystem Linux không hề ngẫu nhiên — nó là một hệ thống được thiết kế cẩn thận:

    • 🔧 /etc — mọi config đều ở đây, backup trước khi sửa
    • 📋 /var — log, cache, runtime data — nơi đầu tiên kiểm tra khi debug
    • 🔬 /proc — cửa sổ vào kernel, real-time, không cần tool thêm
    • ⚙️ /sys — điều chỉnh kernel và hardware on-the-fly
    • 🗑️ /tmp — tạm thời, mount với noexec trong môi trường production

    Hiểu rõ symlink giúp bạn thiết kế deploy pipeline không downtime. Hiểu inode giúp bạn debug những lỗi kỳ lạ khi “file đã xóa mà disk vẫn đầy”. Hiểu mount point giúp bạn thiết kế partition scheme đúng cho server production.

    Bài tiếp theo sẽ đi vào Permissions, Users & Groups — hệ thống phân quyền của Linux và tại sao hiểu đúng chmod, SUID, sudo là điều kiện tiên quyết để làm bảo mật.