宽带私网IPv4开TCP服务,任意主机无客户端直连访问

有消息称国内各大运营商将会逐步收紧家庭宽带分配公网IPv4地址,有些地区已经在执行了,申请改公网IPv4的难度越来越大了。

好消息是几大运营商的固网宽带的CGNAT基本都是NAT1(Full cone)类型的,技术层面上给打洞开TCP服务允许任意公网主机访问提供了可能性。在此也非常感谢v2ex网友mike wang分享了这一思路。

现在,我们可以很方便的借助 natmap 工具来完成私网内的TCP服务端口向公网开放。

1. 适用于路由器拨号的场景,如果是光猫拨号,需要登录光猫配置DMZ。(也有用户反馈光猫实为NAT1无需配置DMZ)
2. 建议将natmap程序运行在拨号路由器上,如果运行在用户侧内网PC上,则同样需要配置拨号路由器的DMZ。
3. 支持调用脚本进行公网地址分发,比如更新到DDNS记录中。

下面以OpenWrt 路由器拨号并将natmap运行在路由器上例举两种基本场景的使用方法,详细使用文档见项目的README。

项目地址: https://github.com/heiher/natmap
程序下载: https://github.com/heiher/natmap/releases

场景一:开放路由器HTTP服务至公网

1. 配置防火墙

配置防火墙允许WAN口访问路由器的TCP 80端口:
登录路由器Web管理页面,转到 网络 -> 防火墙 -> 传输规则,增加如下配置:

* Protocol: TCP
* Source zone: wan
* Destination zone: Device (input)
* Destination port: [bind port]
* Action: accept

2. 运行 natmap

natmap -s stun.stunprotocol.org -h qq.com -b 80

程序运行后会输出映射后的公网IPv4地址和端口,在浏览器中能够访问http://101.82.24.32:43648说明映射成功。

101.82.24.32 43648 2001::aa80:6552:1820 80 tcp

场景二:开放内网PC上SSH服务至公网

1. 运行 natmap

natmap -s stun.stunprotocol.org -h qq.com -b 80 -t 10.0.0.2 -p 22

转发的目标内网主机地址 10.0.0.2,目标端口 22。

场景三:开放内网PC上的WireGuard服务至公网

1. 运行natmap

natmap -u -s stun.qq.com -b 6900 -t 192.168.0.2 -p 6901 -e /usr/bin/ddns

192.168.0.2: 运行WireGuard的内网主机
6901: 运行WireGuard的内网主机端口
/usr/bin/ddns: 将脚本参数3(IP4P)更新到DDNS域名的AAAA记录中。

2. WireGuard Android客户端访问

下载支持IP4P地址格式的WireGuard Android客户端: https://github.com/heiher/wireguard-android/releases/
Peer地址写为:

domain:0

Run OpenWrt 22.03 in systemd-nspawn container

Issue

The dnsmasq can’t start to running.

Why? The ujail is enabled by default on OpenWrt 22.03, and no privilege to do some jail operation in systemd-nspawn container. e.g. mount /tmp/xxx to /dev/log

How to fix

0x1. Uninstall procd-ujail and procd-seccomp

opkg remove procd-ujail
opkg remove procd-seccomp

0x2. Fix dnsmasq service script

/etc/init.d/dnsmasq:

[ -x /sbin/ujail -a -e /etc/capabilities/ntpd.json ] && {
	procd_add_jail dnsmasq ubus log
	procd_add_jail_mount $CONFIGFILE $DHCPBOGUSHOSTNAMEFILE $DHCPSCRIPT $DHCPSCRIPT_DEPENDS
	procd_add_jail_mount $EXTRA_MOUNT $RFC6761FILE $TRUSTANCHORSFILE
	procd_add_jail_mount $dnsmasqconffile $dnsmasqconfdir $resolvdir $user_dhcpscript
	procd_add_jail_mount /etc/passwd /etc/group /etc/TZ /etc/hosts /etc/ethers
	procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile
	case "$logfacility" in */*)
		[ ! -e "$logfacility" ] && touch "$logfacility"
		procd_add_jail_mount_rw "$logfacility"
	esac
}

Stack clash style attacks

What is stack clash style attacks?

计算机上运行的程序都需要一块特殊的内存区域称为“栈”,栈空间通常是动态单向增长的,以Linux内核为例,操作系统为了防止栈空间过早分配产生的内存浪费,采用了栈延迟分配策略,按Page粒度逐步向低地址扩展增长。栈可用空间最低地址位置上有个特殊的页称为Stack Guard Page,当访问到达该页时,将触发严重错误,使程序终止执行。

攻击者故意分配较大的栈空间,但不触发访问,可有可能跳过对Stack Guard Page的访问,如果精心安排,或运气较好,就有可能将低地址方向的其它内存区域作为栈来使用,从而有机会突破栈不可执行保护。

How to prevent?

GCC编译器实现了stack clash protection功能,通过参数-fstack-clash-protection可启用。不是所有的目标架构都实现以支持该功能。

How it works?

GCC实现stack clash protection的方法是为每个函数生成一段代码,该代码执行在业务代码之前,按Page粒度逐个预访问函数framesize空间,达到一定能触发stack guard page访问的目的。

下面以一段MIPS架构汇编代码示例:

#include <stdio.h>

int
main (int argc, char *argv[])
{
    char buffer[1024 * 1024];

    printf ("%p", buffer);

    return 0;
}
00000001200008d0 <main>:                                  
   1200008d0:   03a01825    move    v1,sp                 
   1200008d4:   3c0c0010    lui t0,0x10                   
   1200008d8:   006c602f    dsubu   t0,v1,t0              
   1200008dc:   6463f000    daddiu  v1,v1,-4096           
   1200008e0:   146cfffe    bne v1,t0,1200008dc <main+0xc>
   1200008e4:   fc600000    sd  zero,0(v1)                
   1200008e8:   fd80fff0    sd  zero,-16(t0)              
                                                          
   1200008ec:   67bd8010    daddiu  sp,sp,-32752          
   1200008f0:   3c03000f    lui v1,0xf                    
   1200008f4:   ffbc7fe0    sd  gp,32736(sp)              
   1200008f8:   3c1c0002    lui gp,0x2                    
   1200008fc:   34638020    ori v1,v1,0x8020              
   120000900:   0399e02d    daddu   gp,gp,t9              
   120000904:   ffbf7fe8    sd  ra,32744(sp)              
   120000908:   03a3e82f    dsubu   sp,sp,v1              
   12000090c:   679c83d0    daddiu  gp,gp,-31792          

main函数prolugue中按4096的步长逐个写入了0。

Irreducible loop

Control-flow graph

(a) an if-then-else
(b) a while loop
(c) a natural loop with two exits, e.g. while with an if…break in the middle; non-structured but reducible
(d) an irreducible CFG: a loop with two entry points, e.g. goto into a while or for loop

Java case

IrreducibleLoop.java

public class IrreducibleLoop {
    public static void test(int loop) {
    }
}

IrreducibleLoop.jasm

super public class IrreducibleLoop
    version 63:0
{
  public Method "<init>":"()V" 
    stack 1 locals 1
  {
        aload_0;
        invokespecial    Method java/lang/Object."<init>":"()V";
        return;
  }
  public static Method test:"(I)V" 
    stack 2 locals 2
  {
    L0: iconst_0;
        istore_1;
        iload_0;
        ifne    L2;
    L1: stack_frame_type append;
        locals_map int;
        iload_1;
        iload_0;
        if_icmpge    L3;
    L2: stack_frame_type same;
        goto    L1;
    L3: stack_frame_type chop1;
        return;
  }

} // end Class IrreducibleLoop

Main.java

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 12000; i++) {
            IrreducibleLoop.test(0);
        }
    }
}

Run

javac Main.java
java -jar asmtools-core-7.0.b10-ea.jar jasm IrreducibleLoop.jasm
java -XX:TieredStopAtLevel=1 -Xcomp -XX:CompileCommand=compileonly,IrreducibleLoop::* Main

Refer

https://en.wikipedia.org/wiki/Control-flow_graph

ch341-uart converter now disconnected from ttyUSB0

usb 1-3.4: USB disconnect, device number 18
usb 1-3.1: new full-speed USB device number 19 using xhci_hcd
usb 1-3.1: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.54
usb 1-3.1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
usb 1-3.1: Product: USB2.0-Ser!
ch341 1-3.1:1.0: ch341-uart converter detected
ch341-uart ttyUSB0: break control not supported, using simulated break
usb 1-3.1: ch341-uart converter now attached to ttyUSB0
usb 1-3.1: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
ch341 1-3.1:1.0: device disconnected

Solution

sudo mv /usr/lib/udev/rules.d/90-brltty-device.rules /usr/lib/udev/rules.d/90-brltty-device.rules.disabled
sudo mv /usr/lib/udev/rules.d/90-brltty-uinput.rules /usr/lib/udev/rules.d/90-brltty-uinput.rules.disabled
sudo udevadm control --reload-rules