Transparent proxy with nftables

This is an example of configuring transparent proxy(tproxy) with nftables. The tproxy application is hev-socks5-tproxy

Netfilter rules

DON’T FORGOT TO ADD UPSTREAM ADDRESS TO BYPASS IPSET!!
Or use nftables skuid/skgid match to exclude proxy process.

table inet mangle {
    set byp4 {
        typeof ip daddr
        flags interval
        elements = { 0.0.0.0/8, 10.0.0.0/8,
                 127.0.0.0/8, 169.254.0.0/16,
                 172.16.0.0/12, 192.0.0.0/24,
                 192.0.2.0/24, 192.88.99.0/24,
                 192.168.0.0/16, 198.18.0.0/15,
                 198.51.100.0/24, 203.0.113.0/24,
                 224.0.0.0/4, 240.0.0.0-255.255.255.255 }
    }

    set byp6 {
        typeof ip6 daddr
        flags interval
        elements = { ::,
                 ::1,
                 ::ffff:0:0:0/96,
                 64:ff9b::/96,
                 100::/64,
                 2001::/32,
                 2001:20::/28,
                 2001:db8::/32,
                 2002::/16,
                 fc00::/7,
                 fe80::/10,
                 ff00::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff }
    }

    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;
        ip daddr @byp4 return
        ip6 daddr @byp6 return
        tcp dport { 0-65535 } tproxy to :1088 meta mark set 0x00000440 accept
        udp dport { 0-65535 } tproxy to :1088 meta mark set 0x00000440 accept
    }

    # Only for local mode
    chain output {
        type route hook output priority mangle; policy accept;
        ip daddr @byp4 return
        ip6 daddr @byp6 return
        tcp dport { 0-65535 } meta mark set 0x00000440
        udp dport { 0-65535 } meta mark set 0x00000440
    }
}

Routing rules

ip rule add fwmark 1088 table 100
ip route add local default dev lo table 100
 
ip -6 rule add fwmark 1088 table 100
ip -6 route add local default dev lo table 100

See also: https://github.com/heiher/hev-socks5-tproxy/blob/master/README.md

The nftables config file that bypass all IPv4 and IPv6 sets of China: https://gist.githubusercontent.com/heiher/fd001c69eda8d1f87bb66c3f44509c11/raw/nftables.conf

GNOME Terminal Bold Font

Enable bold font for GNOME Terminal:

0x01

# Get profile id
dconf dump /org/gnome/terminal/legacy/
 
# Set bold font
dconf write /org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/font "'Monospace Bold 14'"

0x02
Preferences->Profiles->->Colors:
Select “Show bold text in bright colors”

Catch exception thrown from memory references

By default an exception can only occur during a function call or a throw. If we needs to catch excpetions thrown from trapping instructions, using the `-fnon-call-exceptions`.

Docs:

-fnon-call-exceptions

Generate code that allows trapping instructions to throw exceptions. Note that this requires platform-specific runtime support that does not exist everywhere. Moreover, it only allows trapping instructions to throw exceptions, i.e. memory references or floating point instructions. It does not allow exceptions to be thrown from arbitrary signal handlers such as SIGALRM. 

Example:

#include <iostream>
 
#include <signal.h>
 
using namespace std;
 
static void
sigsegv_handler (int signo)
{
    throw 0;
}
 
int
main (int argc, char *argv[])
{
    int *ptr = nullptr;
    int res;
 
    signal (SIGSEGV, sigsegv_handler);
 
    try {
        res = *ptr;
    } catch (...) {
        cout << "exception" << endl;
    }
 
    return res;
}
g++ -fnon-call-exceptions -o sig sig.cpp

Refernces:
[1] https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

Load shared libraries with preferred base address

For performance, sometimes we need to adjust the address space layout. The following way allows the shared or executable object to be loaded with preferred base address.

When the dynamic link maps the shared object, the virtual address of segment(that in ELF program header) will be used as the mapping address hints.

Type 1
Link with text-segment starting address.

# Adjust base address to 0x10000 */
gcc -shared ... -Wl,-Ttext-segment=0x10000

Type 2
We can adjust the virtual address of loaded segment by linker scripts.

0x1 Get link script template

gcc -shared -Wl,--verbose > ld.script

Clear the contents before and after the ‘equal sign’.

0x2 Adjust the base address

....
SECTIONS
{
    /* Adjust base address to 0x10000 */
    . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
    ...
}
....

0x3 Link with script

gcc -shared ... -Wl,-T ld.script

Over!