Phantun

https://www.v2ex.com/t/802949
https://github.com/dndx/phantun
作者: dndx

将 UDP 流量伪装成 TCP 流量的主流工具是 udp2raw

Phantun 的目标不是为了替代 udp2raw,从一开始 Phantun 就希望设计足够的简单高效,所以 udp2raw 支持的 ICMP 隧道,加密,防止重放等等功能 Phantun 都选择不实现。

Phantun 假设 UDP 协议本身已经解决了这些问题,所以整个转发过程就是简单的明文换头加上一些必要的 TCP 状态控制信息。对于我日常使用的 WireGuard 来说,Phantun 这种设计是足够安全的,因为 WireGuard 的协议已经更好的实现了这些安全功能。

Phantun 使用 TUN 接口来收发 3 层数据包,udp2raw 使用 Raw Socket + BFP 过滤器。个人感觉基于 TUN 的实现要稍微的优雅一点,而且跨平台移植也要更容易。

Phantun 的 TCP 连接是按需创建的,只启动 Client 不会主动去连接服务器,需要第一个数据包到达了后才会按需创建。每个 UDP 流都有自己独立的 TCP 连接。这一点跟 udp2raw 很不一样,udp2raw 所有的 UDP 连接共用一个 TCP 连接。这样做的坏处就是 udp2raw 需要额外的头部信息来区分连接,更加增加了头部的开销。跟纯 UDP 比较,Phantun 每个数据包的额外头部开销是 12 byte,udp2raw 根据我的测试达到了 44 bytes 。

https://icloudnative.io/posts/wireguard-over-tcp-using-phantun/

https://icloudnative.io/posts/custom-derp-servers/

0. 编译
… 过程省略 .. 参考 rust 相关帖子

1. 在服务器上配置,运行

设置转发
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination 192.168.201.2

运行

RUST_LOG=info  ./server --local 4567 --remote 127.0.0.1:1234
 INFO  server > Remote address is: 127.0.0.1:1234
 INFO  server > 1 cores available
 INFO  server > Created TUN device tun0
 INFO  server > Listening on 4567

创建tun

tun0
    inet 192.168.201.1 peer 192.168.201.2/32 scope global tun0

让第三方的 UDP 服务,监听在 127.0.0.1的1234 端口

2. 客户端配置,运行

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

运行
RUST_LOG=info ./client --local 127.0.0.1:1234 --remote server_ip:4567

监听在本地的 127.0.0.1的1234端口

第3方客户端, 直接连接到 127.0.0.1:1234 就相当于 连接到 远程的UDP服务

建立一个tun0

tun0: 
    inet 192.168.200.1 peer 192.168.200.2/32 scope global tun0

phantun监听在本地的 127.0.0.1:1234 UDP, 同时创建了一个 tun0设备, tun0设备的本端ip为 192.168.200.1, 对端ip为
192.168.200.2
来自于 123 udp端口的的 数据, 都被以 192.168.200.2的IP, 连接到 server_ip:4567 用tcp发送出去

但这个tcp连接, 又被 iptable改写了 源地址, 从 192.168.200.2 改成 了 客户端自己的主机地址

3. 测试程序

#!/usr/bin/env python 

 
import socket 
import sys 
import argparse 
from time     import sleep
 
host = '127.0.0.1' 
payload_size = 2048 
 
def echo_server(peer,  bind_port, to_port): 
    sock = socket.socket(socket.AF_INET,  socket.SOCK_DGRAM) 
    server_address = (host, bind_port) 
    print ("Starting up echo server on %s port %s" % server_address) 
    sock.bind(server_address) 
    sock.settimeout(5.0)
    
    index = 1
 
    while True: 
        try:
            print ("Waiting to receive message  from client") 
            data, address = sock.recvfrom(payload_size) 
         
            print ("received %s bytes from %s" % (len(data), address)) 
            print ("Data: %s" %data) 
         
            if data: 
                #data = b'###...' + data + b'...###'
                data = b'### %i' % index
                sent = sock.sendto(data, address) 
                print ("sent %s bytes back to %s" % (sent, address))
                index = index + 1
                sleep(1)
        except socket.timeout:
            #addr = (peer, to_port)
            #data = b'count %i' % index
            #sent = sock.sendto(data, addr) 
            #print ("sent %s bytes hello to %s" % (sent, addr)) 
            index = index + 1
 
 
if __name__ == '__main__': 
    parser = argparse.ArgumentParser(description='Socket Server Example') 
    parser.add_argument('--host', action="store", dest="host", type=str, required=True)     
    parser.add_argument('--bind', action="store", dest="bind_port", type=int, required=True) 
    parser.add_argument('--to', action="store", dest="to_port", type=int, required=True) 
        
    given_args = parser.parse_args()
    peer = given_args.host    
    local_port = given_args.bind_port
    remote_port = given_args.to_port    
 
    
    echo_server(peer, local_port, remote_port) 

在服务端运行

python3 ttt_echo_server.py  --host  cliet_peer_ip  --bind  1234  --to 9999

监听在udp的1234端口

在客户端运行

python3 ttt_echo_server.py --host 127.0.0.1 --bind 9999 --to 1234

它会往 本地 127.0.0.1 的1234 udp端口发送数据, 从而fake tcp转发给 服务器

INFO fake_tcp > Sent SYN to server
INFO fake_tcp > Connection to 111.222.333.444:4567 established

4. 关于MTU
WireGuard MTU = Interface MTU – IPv4 header (20 bytes) – TCP header (20 bytes) – WireGuard overhead (32 bytes)
IPv4: 1500 – 20 – 20 – 32 = 1428
phantun作者介绍的,应该这么算, 但我实际设置为 1480 也是通的

he tb ipv6后

ping -c 2  -M do  -4    -s  1364    10.0.0.1

ipv4 直连 (MTU居然只有1400)

ping   -c 2  -M do  -4    -s  1372  server_public_ip
1372(1400)

ipv4 udp wireguard直连

ping -c 2  -M do  -4    -s  1452    10.0.0.1

1452(1480)

ipv4 tcp wireguard

 ping -c 2  -M do  -4    -s  1396    10.0.0.1

实际浪费56个字节

IPV4 20
IPCP 16

Usually the MTU of most networks is 1500. So the MTU of IPv6 tunnel should be 1480 by removing the 20 bytes IPv4 header. To set a proper MTU that neither cause IPv6 packet be truncated nor be too small for IPv6, You’d better find the IPv4 MTU from you to your tunnel relay server by your self and set the IPv6 MTU by minus 20 bytes.

5. 几个坑点
(1) 在服务器上,如果运行的是

./server --local 4567 --remote 127.0.0.1:1234

也就是转发给 127.0.0.1:1234 这个 udp监听端口, 必须严格监听在 127.0.0.1:1234
监听在 0.0.0.0:1234 是不能正常工作的
(2)客户端, iptable命令的出口 网卡名字必须正确指定

iptables  -t nat -A POSTROUTING -o br0  -j MASQUERADE

如果用了网桥, 必须设置为网桥的名字

cjdns

https://github.com/cjdelisle/cjdns

UDP协议

编译需要rust和nodejs环境

cd /opt
git clone https://github.com/cjdelisle/cjdns.git
cd cjdns
./do
ln -s /opt/cjdns/cjdroute /usr/bin
(umask 077 && ./cjdroute --genconf > /etc/cjdroute.conf)
cp contrib/systemd/*.service /etc/systemd/system/
systemctl enable cjdns
systemctl start cjdns

yggdrasil

https://github.com/yggdrasil-network/public-peers
https://github.com/yggdrasil-network/yggdrasil-android
https://github.com/yggdrasil-network/crispa-android

vpncloud

https://vpncloud.ddswd.de/
https://github.com/dswd/vpncloud/

VpnCloud 是基于 UDP 的高性能点对点网状 VPN,支持强大的加密、NAT 穿越和简单的配置。 它以基于椭圆曲线密钥和 AES-256 的强大端到端加密的对等方式建立全网状自愈 VPN 网络。 VpnCloud 在主机上创建一个虚拟网络接口,并通过 UDP 将所有接收到的数据转发到目的地。 它可以在 TUN 设备(基于 IP)和 TAP 设备(基于以太网)上工作

Rust开发的

最大缺点是没有Android 客户
Tinc, Nebula, Wireguard 都有

Tinc uses UDP and TCP for connections. There is no option to only use the more efficient UDP.

Tinc requires users to create a key pair for each node and then exchange the public keys with all other nodes.

Nebula has a centralized take on security: It introduces a central authority that issues certificates for all nodes. The certificates also contain an allowed IP address, that will be enforced by other nodes. Nebula supports two symmetric ciphers (AES256 and ChaCha20) but the cipher has to be the same for the whole network.

Wireguard achieves its high throughput because it uses a kernel module to do the heavy lifting.

nebula vpn

https://github.com/slackhq/nebula
https://github.com/DefinedNet/mobile_nebula

Nebula is a scalable overlay networking tool with a focus on performance, simplicity and security. It lets you seamlessly connect computers anywhere in the world. Nebula is portable, and runs on Linux, OSX, Windows, iOS, and Android. It can be used to connect a small number of computers, but is also able to connect tens of thousands of computers.

Configure Nebula VPN on iOS/Android
https://willhbr.net/2021/06/22/configure-nebula-vpn-on-ios-android/

VPN mesh with Nebula
https://linuxblog.xyz/posts/slack-nebula/

在debian中安装 nebula-lighthouse-service 灯塔服务

UDP/noiseprotocol协议

NaiveProxy

浏览器 → NaiveProxy客户端 ⟶ GFW ⟶ 常用前端(Caddy/HAProxy等) → NaiveProxy服务端 ⟶ 互联网

使用Chrome的网络堆栈,GFW审查截获的流量行为与Chrome和标准前端(如 Caddy、HAProxy)之间的常规 HTTP/2 流量完全相同。前端还会将未经身份验证的用户和活动探测器重新路由到后端HTTP服务器,从而使得无法检测到代理的存在,比如像这样:探查⟶常用前端⟶网站页面。

https://github.com/klzgrad/naiveproxy

0. 安装Go开发环境

 下载
cd ~/
wget "https://go.dev/dl/$(curl https://go.dev/VERSION?m=text).linux-amd64.tar.gz"
解压缩
tar xvaf go1.19.3.linux-amd64.tar.gz
mv go golang
mkdir go
配置环境变量
export GOROOT=$HOME/golang
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$GOBIN:$GOROOT/bin:$PATH

1. 安装编译caddy

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy@caddy2=github.com/klzgrad/forwardproxy@naive
或
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy=github.com/klzgrad/forwardproxy@naive

编译成功后,可以看到当前目录中存在一个名为caddy的文件。
https://github.com/klzgrad/naiveproxy/wiki/%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87 中介绍的方法有点过时

2. 配置caddy
创建一个 config.json

:443, softs.im
tls email@softs.im
route {
        forward_proxy {
                basic_auth username passwd
                hide_ip
                hide_via
                probe_resistance
        }
        file_server {
                root /home/softsim/www
        }
}

更好一点的配置

{
        order forward_proxy before file_server
}
:443, nr5g.softs.im {
        tls /home/softsim/ssl/softsim.cer /home/softsim/ssl/softsim.key

        forward_proxy {
                basic_auth myuser mypasswd
                hide_ip
                hide_via
                probe_resistance
        }

        root * /home/softsim/nr5g
        encode gzip
        php_fastcgi unix//run/php/php8.1-fpm.sock
        file_server
}

lte.softs.im {
        tls /home/softsim/ssl/softsim.cer /home/softsim/ssl/softsim.key
        file_server {
                root /var/lib/transmission-daemon/downloads
        }
}

注意:
(1) 用您的实际电子邮件地址替换 email@softs.im 用来接收 Let’s Encrypt 通知
或者用 文件配置 已经申请好的证书
tls /path/example.com.crt /path/example.com.key

将其格式化

caddy fmt --overwrite /etc/caddy/Caddyfile

注意:不格式化,caddy运行会报错
并且,还得用 /etc/caddy/Caddyfile 这个名字, 用别的文件名会出错

如果想建立多用户版Naive,可以将 forward_proxy 模块复制。将basic_auth中的用户密码修改成另外一个就可以了。

运行

# 以后台的方式启动 caddy
caddy start --config  /etc/caddy/Caddyfile

# 以前台的方式启动 caddy
caddy run --config  /etc/caddy/Caddyfile


caddy stop

3. 编译naiveproxy客户端

git clone --depth 1 https://github.com/klzgrad/naiveproxy.git
cd naiveproxy/src/
./get-clang.sh
./build.sh

编译出的文件为 out/Release/naive

配置naiveproxy 客户端

{
  "listen": "socks://127.0.0.1:1080",
  "proxy": "https://username:passwd@softs.im"
}

保存为np.json
运行

./naive np.json

4. 配置浏览器的 SmartProxy或者SwitchyOmega 来自动匹配要代理的网站
…..

5. 让caddy以systemd 的守护进程运行

mv  caddy  /usr/bin/
setcap cap_net_bind_service=+ep  /usr/bin/caddy

添加 /etc/systemd/system/caddy.service 文件,内容如下

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=www-data
Group=www-data
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

启用服务

 systemctl daemon-reload
 systemctl enable caddy
 systemctl start caddy

6. 支持一般PHP的配置

        root * /home/softsim/simpleforum
        php_fastcgi unix//run/php/php7.4-fpm.sock
        file_server

tinyfecVPN和udp2raw

https://github.com/wangyu-/tinyfecVPN

tinyfecVPN

工作在VPN方式的双边网络加速工具,可以加速全流量(TCP/UDP/ICMP)。

tinyfecVPN使用了和UDPSpeeder相同的lib,功能和UDPspeeder类似,只不过tinyfecVPN工作方式是VPN,UDPspeeder工作方式是UDP tunnel.

tinyfecVPN是无状态的点对点VPN, 收到包即连接建立成功;即使VPN断线重连,上层承载的连接不掉线。

https://github.com/wangyu-/udp2raw/blob/unified/doc/README.zh-cn.md

udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS,或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。

支持心跳保活、自动重连,重连后会恢复上次连接,在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。

Linux主机,有root权限或cap_net_raw capability.。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令

最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器,把udp2raw运行在路由器上。

把udp流量伪装成tcp /icmp

用raw socket给udp包加上tcp/icmp包头,可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下,提升稳定性。 另外也支持用raw 发udp包,这样流量不会被伪装,只会被加密。
模拟TCP3次握手

模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
心跳保活、自动重连,连接恢复

心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自kcptun-raw)(就算你拔掉网线重插,或者重新拨号获得新ip,上层应用也不会断线)
================

https://github.com/wangyu-/tinyfecVPN/wiki/%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C

用udp2raw防止tinyfecVPN被限速或断流

udp2raw可以把udp流量伪装成tcp,防止udp被运营商限速或断流。即使发生断流,udp2raw可以检测到这种情况并自动帮你重连。

推荐tinyfecVPN和udp2raw一起使用。连接方式:

tinyfecVPN client—->udp2raw client—————>udp2raw server—->tinyfecVPN server
=========================

n2n和omniedge

https://github.com/ntop/n2n
https://github.com/switch-iot/hin2n/blob/dev/README_zh.md

https://github.com/omniedgeio/omniedge (类似于nebula和headscale之类的东西)

debian bookworm安装配置Kamailio

bookworm上的kamailio很新,5.6.2版本

1. 先安装MariaDB

apt install default-mysql-server

2. 切换到root用户, 执行

#  mysql -u root -p

然后在 mysql 的shell里修改 mysql数据库的root密码

ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

因为配置Kamailio时,要用到mysql 的root用户密码

3. 安装 Kamailio

apt install kamailio kamailio-mysql-modules

4. 配置
配置文件 在 /etc/kamailio/ 目录下,有两个
一个是 /etc/kamailio/kamctlrc, 里面的配置信息,主要供 kamctl 和 kamdbctl 这两个工具命令使用

SIP_DOMAIN=
DBENGINE=MYSQL
DBRWUSER=
DBRWPW=
CHARSET="latin1"
---上面5个必须修改----
DBROUSER=
DBROPW=
DBHOST=
DBPORT=

SIP_DOMAIN可以是域名 或者 IP地址

另外一个是 /etc/kamailio/kamailio.cfg, 是供 kamailio 主程序使用的, 里面有很多 脚本

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB

#!define DBURL "mysql://kamailio:_NEW_DBRWPW_@localhost/kamailio"

这四个选项必须修改

如果设置了SIP_DOMAIN为域名,但这个域名没有在DNS中解析, 还必须在 kamailio.cfg 设置一个选项

alias=""

5. 初始化数据库和用户

kamdbctl create

这个时候会要求输入mysql的root密码

6. 开启停止服务

systemctl start kamailio
systemctl stop kamailio
systemctl restart kamailio

7. 添加用户

kamctl add userid password
比如
kamctl add  softsimuser  softsimpassword

8. 监听 IPV6地址

listen=udp:10.0.0.10:5060

listen=[proto]:[localip]:[lport] advertise [publicip]:[pport]

如果不设置,只监听本地 ipv4地址
或者使用

auto_bind_ipv6=1

选项

9. 常用管理命令

查看用户
/usr/sbin/kamctl db show subscriber

添加用户
/usr/sbin/kamctl add  softsimuser  softsimpassword

修改用户密码
/usr/sbin/kamctl   passwd  username  passwd

显示在线用户
/usr/sbin/kamctl    online

删除用户
/usr/sbin/kamctl  rm   username


启动Kamalio
/usr/sbin/kamctl  start  

重启Kamalio
/usr/sbin/kamctl  restart 


停止Kamalio
/usr/sbin/kamctl         stop