Thursday, October 9, 2025

Debian 13: part 1 install Tor-Project

Tor Project's repository only support amd64, arm64, or i386 architectures.

# dpkg --print-architecture
amd64

Install apt-transport-https

# apt install apt-transport-https gnupg

Add Tor Project repository into debian machince

  1. Create a new file in /etc/apt/sources.list.d/ named tor.list
  2. Filled /etc/apt/sources.list.d/tor.list with:
    deb     [signed-by=/usr/share/keyrings/deb.torproject.org-keyring.gpg] https://deb.torproject.org/torproject.org trixiemain
    deb-src [signed-by=/usr/share/keyrings/deb.torproject.org-keyring.gpg] https://deb.torproject.org/torproject.org trixie main

Currently, Tor repository only support bookworm, bullseye and trixie.

Add gpg key for Tor Project's repository 

# wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/null

If asc file does not exist, use your browser to open https://deb.torproject.org/torproject.org/. It will open directory of /torproject.org. Find file's name with asc, copy the file name and replace A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc with the new one. 

Install Tor Project key's

# apt install tor deb.torproject.org-keyring

Installing Tor

# apt install tor

 

Tuesday, October 7, 2025

Debian 13: general nftables with set for web server and router

This is general nftables for apache, ssh, dns ntp 

#!/usr/sbin/nft -f

flush ruleset

table inet filter {

    # Set for common inbound web server ports

    set web_ports {

        type inet_service;

        flags interval;

        elements = { 80, 443 }

    }

    # Set for other essential services, like SSH, DNS, and NTP

    set services {

        type inet_service;

        elements = { 22, 53, 123 }

    }

    chain input {

        type filter hook input priority 0; policy drop;

        # Allow connections that are part of an existing or related session

        ct state established,related accept

        # Drop invalid packets

        ct state invalid drop

        # Allow traffic from the loopback interface

        iif "lo" accept

        # Allow incoming traffic for common web services

        tcp dport @web_ports accept

        # Allow incoming SSH, DNS, and NTP traffic

        tcp dport @services accept

        udp dport @services accept

        # Allow incoming ICMP (ping) packets for diagnostics

        icmp type echo-request accept

        # Log and drop any other incoming traffic

        meta protocol vmap { ip : log prefix "[NFT-DROP]: ", ip6 : log prefix "[NFT-DROP]: " }

        meta protocol vmap { ip : drop, ip6 : drop }

    }

    chain forward {

        type filter hook forward priority 0; policy drop;

    }

    chain output {

        type filter hook output priority 0; policy accept;

    }

}

This is nftable for general router

  • eth0 to internet/router
  • eth1 to lan 

Edit/create nano /etc/sysctl.conf

net.ipv4.ip_forward=1

nftables rules

#!/usr/sbin/nft -f

# Clear all existing rules

flush ruleset

# --- Define variables for interfaces and networks ---

define wan_if = eth0

define lan_if = eth1

define lan_net = 192.168.1.0/24

# === Table for IPv4/IPv6 filtering ===

table inet filter {

    # Set for essential services (SSH, DNS, NTP)

    set essential_services {

        type inet_service;

        elements = { 22, 53, 123 }

    }

    # Set for web server ports

    set web_ports {

        type inet_service;

        flags interval;

        elements = { 80, 443 }

    }

    # Set of trusted interfaces (LAN)

    set trusted_interfaces {

        type ifname;

        elements = { $lan_if }

    }

    # Set of untrusted interfaces (WAN)

    set untrusted_interfaces {

        type ifname;

        elements = { $wan_if }

    }

    # --- INPUT chain: Controls traffic destined for the router itself ---

    chain input {

        type filter hook input priority 0; policy drop;

        # Accept packets that are part of an established or related connection

        ct state established,related accept

        # Drop any packets with an invalid connection state

        ct state invalid drop

        # Allow traffic from the loopback interface

        iif "lo" accept

        # Allow all traffic from the trusted LAN interfaces

        iifname @trusted_interfaces accept

        # Allow incoming SSH, DNS, and NTP from the internet (rate limited)

        iifname @untrusted_interfaces tcp dport @essential_services limit rate 10/minute accept

        iifname @untrusted_interfaces udp dport @essential_services limit rate 10/minute accept

        # Allow incoming web traffic (Apache) from the internet

        iifname @untrusted_interfaces tcp dport @web_ports accept

        # Allow ICMP (ping) from the internet, but rate-limit it

        iifname @untrusted_interfaces icmp type echo-request limit rate 5/second accept

        # Log and drop everything else coming from untrusted interfaces

        iifname @untrusted_interfaces log prefix "NFT-INET-DROP: "

        iifname @untrusted_interfaces drop

        # Catch-all log and drop for other incoming traffic

        log prefix "NFT-INPUT-DROP: "

        drop

    }

    # --- FORWARD chain: Controls traffic passing *through* the router ---

    chain forward {

        type filter hook forward priority 0; policy drop;

        # Accept packets that are part of an established or related connection

        ct state established,related accept

        # Drop invalid packets

        ct state invalid drop

        # Allow outbound traffic from the LAN to the internet

        iifname @trusted_interfaces oifname @untrusted_interfaces accept

        # Log and drop any other forwarded traffic

        log prefix "NFT-FORWARD-DROP: "

        drop

    }

    # --- OUTPUT chain: Controls traffic originating from the server ---

    chain output {

        type filter hook output priority 0; policy accept;

    }

}

# === NAT table for IPv4 (needed for internet access from LAN) ===

table ip nat {

    # --- PREROUTING chain: Used for incoming traffic before routing ---

    chain prerouting {

        type nat hook prerouting priority 0;

        # Example: Port forward incoming web traffic from the internet to a specific LAN machine

        # iifname $wan_if tcp dport { 80, 443 } dnat to 192.168.1.100

    }

    # --- POSTROUTING chain: Used for outgoing traffic after routing ---

    chain postrouting {

        type nat hook postrouting priority 100;

        # Masquerade traffic leaving the internet interface

        oifname $wan_if masquerade

    }

}


Monday, October 6, 2025

Debian 13: How to save ai solution with mathematical formula into odt file

After you ask AI, and AI give you solution with mathematical formula. You can not directly to copy-paste the result into libreoffice writer nor microsoft word.

1. Ask your AI to show the result in latex format.

2. Copy paste the result into text file e.q. example.text.

3. Create empty odt file e.q. output.odt 

4. Use pandoc application to convert it into odt.

$ pandoc -f latex -t odt -o output.odt example.text

    if the input file is latin1 encoded, like my text files, the solution is (imo the best output):

$ iconv -f ISO-8859-1 example.text | pandoc -f latex -t odt -o tmp.odt

    WARNING: this command will replace any content in tmp.odt and output.odt. 

5. Now, you can open odt with mathematical formula. 

To install pandoc and iconv (part of libc-bin) 

# apt-get install pandoc libc-bin libreoffice-texmaths

 

Sunday, October 5, 2025

Debian 13: moving from iptables to nftables

Nftables has been introduced from debian 10. iptables still available until debian 12. since debian 13, nftables is the default firewall. there is iptables-nft layer if user still want to interact with nftables with iptables command with some limitation due to they have different way to manage firewall.

The nftables flow to create firewall rules:

  1. Create rule
  2. Create a table
  3. Create a chain
  4. Create a set (for IPv4 or IPv6)

Add rule(s) that match against that set, we’re using the inet family, the same output chain can handle both IPv4 and IPv6. These is /etc/nftables.conf for pc 

  1. any connection from localhost  to outside
  2. accept incoming connection for port http, https and ssh from outside
  3. block incoming access from ip 1.2.3.4 
  4. block incoming access from ip 1.2.3.5 for port ssh

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    # Define a set for allowed TCP ports
    set allowed_tcp_ports {
        type inet_service;
        elements = { 22, 80, 443 }
    }

    # Define a set for blocked IPv4 addresses (all traffic)
    set blocked_ips {
        type ipv4_addr;
        elements = { 1.2.3.4 }
    }

    # Define a set for IPs blocked only on SSH
    set ssh_blocked_ips {
        type ipv4_addr;
        elements = { 1.2.3.5 }
    }

    chain input {
        type filter hook input priority 0; policy drop;

        # Drop packets from blocked IPs (all traffic)
        ip saddr @blocked_ips drop

        # Drop SSH packets from ssh_blocked_ips
        tcp dport 22 ip saddr @ssh_blocked_ips drop

        # Allow loopback interface
        iif lo accept

        # Accept established and related connections
        ct state established,related accept

        # Allow ICMP (ping)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # Allow TCP packets to ports in allowed_tcp_ports set
        tcp dport @allowed_tcp_ports accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

To add element in blocked_ips (temporary, need to save)

# nft add element inet filter blocked_ips { 5.6.7.8 }

To replace the whole element in blocked_ips (temporary, need to save)

# nft replace set inet filter blocked_ips { elements = { 1.2.3.4, 2.3.4.5 } }

To delete an element in blocked_ips (temporary, need to save)

# nft delete element inet filter blocked_ips { 203.0.113.5 }

To store/save nftables permanently  

# nft list ruleset > /etc/nftables.conf

This command will clean/remove all rules until nftables.conf reload

# nft flush ruleset

Back to iptables, in iptables the rules store and restore with following command:

# nft list ruleset > my_rules.nft
# nft -f my_rules.nft 

This is vulnerable to the system, there is a delay when system ready but not protected by firewall until system fully loading the the firewall rules. This weakness has been eliminate in nftables, nftables uses systemd to load the firewall. Firewall was loaded before system ready.

To enable nftables and start

# systemctl enable nftables
# systemctl start nftables

To export set blocked_ips in nftables

# nft list set inet filter blocked_ips > blocked_ips.conf
# nft -f blocked_ips.conf

These are more cleaner nftables.conf, set will be put on different file

/etc/nftables.conf:

#!/usr/sbin/nft -f

flush ruleset

include "/etc/nftables.d/sets-common.nft"
include "/etc/nftables.d/sets-ipv4.nft"
include "/etc/nftables.d/sets-ipv6.nft"

table inet filter {

    chain input {
        type filter hook input priority 0; policy drop;

        ip saddr @blocked_ips_v4 drop
        ip6 saddr @blocked_ips_v6 drop

        tcp dport 22 ip saddr @ssh_blocked_ips_v4 drop
        tcp dport 22 ip6 saddr @ssh_blocked_ips_v6 drop

        iif lo accept

        ct state established,related accept

        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        tcp dport @allowed_tcp_ports accept
        tcp dport @allowed_tcp_ports accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

/etc/nftables.d/sets-common.nft: 

table inet filter {
    set allowed_tcp_ports {
        type inet_service;
        elements = { 22, 80, 443 }
    }
}

/etc/nftables.d/sets-ipv4.nft: 

table inet filter {
    set blocked_ips_v4 {
        type ipv4_addr;
        elements = { 1.2.3.4 }
    }

    set ssh_blocked_ips_v4 {
        type ipv4_addr;
        elements = { 1.2.3.5 }
    }
}

/etc/nftables.d/sets-ipv6.nft:

table inet filter {
    set blocked_ips_v6 {
        type ipv6_addr;
        elements = { 2001:db8::dead:beef }
    }

    set ssh_blocked_ips_v6 {
        type ipv6_addr;
        elements = { 2001:db8::cafe:babe }
    }
}

 

Wednesday, October 1, 2025

Moving apace, mariadb and php project from a debian site to other debian site

I want to create a bash script to backup and restore the project (apache, mariadb and php) easily. I need to work at 2 debian machine with the same configuration in 2 different location. I ask to duck.ai to solve the problem. Here is the result.

Create a file myconfig.conf

# myconfig.conf
DB_NAME="your_database_name"
DB_USER="your_username"
DB_PASS="your_password"
PROJECT_ROOT="/path/to/your/php/project"  # Add this line

Create bash script mybackup.sh 

#!/bin/bash

# Load database configuration from myconfig.conf
source myconfig.conf

# Create a backup file name for the database
DB_BACKUP_FILE="${DB_NAME}_$(date +%Y-%m-%d).sql"
# Create a zip file name for the project
PROJECT_BACKUP_FILE="$(basename "$PROJECT_ROOT")_backup_$(date +%Y-%m-%d).zip"

# Function to backup the database
backup_database() {
    echo "Backing up database: $DB_NAME"
    mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$DB_BACKUP_FILE"
    if [ $? -eq 0 ]; then
        echo "Database backup successful: $DB_BACKUP_FILE"
    else
        echo "Database backup failed!"
        return 1
    fi
}

# Function to zip the project files
zip_project() {
    echo "Zipping project files from: $PROJECT_ROOT"
    zip -r "$PROJECT_BACKUP_FILE" "$PROJECT_ROOT"
    if [ $? -eq 0 ]; then
        echo "Project backup successful: $PROJECT_BACKUP_FILE"
    else
        echo "Project backup failed!"
        return 1
    fi
}

# Function to restore the database
restore_database() {
    echo "Restoring database: $DB_NAME from $1"
    mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$1"
    if [ $? -eq 0 ]; then
        echo "Database restore successful!"
    else
        echo "Database restore failed!"
    fi
}

# Function to unzip the project files
unzip_project() {
    echo "Unzipping project files to: $PROJECT_ROOT"
    unzip -o "$1" -d "$PROJECT_ROOT"
    if [ $? -eq 0 ]; then
        echo "Project restore successful!"
    else
        echo "Project restore failed!"
    fi
}

# Check command line arguments
if [ "$1" == "backup" ]; then
    backup_database
    zip_project
elif [ "$1" == "restore" ]; then
    if [ -z "$2" ] || [ -z "$3" ]; then
        echo "Please provide the SQL backup file and the project zip file to restore from."
        exit 1
    fi
    SQL_BACKUP_FILE="$2"
    PROJECT_BACKUP_FILE="$3"
    restore_database "$SQL_BACKUP_FILE"
    unzip_project "$PROJECT_BACKUP_FILE"
else
    echo "Usage: $0 {backup|restore [sql_backup_file] [project_backup_file]}"
    exit 1
fi

To backup

./mybackup.sh backup

It will create 2 files

  1. zip for backup and restore web root project
  2. sql for backup and restore mariadb database 

To restore

./mybackup.sh restore your_database_backup.sql your_project_backup_file.zip