mirror of
https://gitee.com/konyshe/goodlink.git
synced 2025-10-30 19:56:20 +08:00
add support for linux and udp
This commit is contained in:
15
Makefile
15
Makefile
@@ -11,8 +11,7 @@ GOBUILD=GO111MODULE=on \
|
|||||||
-X "gogo.BuildTime=$(BuildTime)" \
|
-X "gogo.BuildTime=$(BuildTime)" \
|
||||||
-w -s -buildid='
|
-w -s -buildid='
|
||||||
|
|
||||||
PLATFORM_LIST = \
|
LINUX_PLATFORM_LIST = \
|
||||||
windows-amd64-ui \
|
|
||||||
linux-386-cmd \
|
linux-386-cmd \
|
||||||
linux-amd64-cmd \
|
linux-amd64-cmd \
|
||||||
linux-arm-cmd \
|
linux-arm-cmd \
|
||||||
@@ -23,11 +22,14 @@ PLATFORM_LIST = \
|
|||||||
linux-mipsle-cmd \
|
linux-mipsle-cmd \
|
||||||
linux-mips64-cmd \
|
linux-mips64-cmd \
|
||||||
linux-riscv64-cmd \
|
linux-riscv64-cmd \
|
||||||
linux-mips64le-cmd \
|
linux-mips64le-cmd
|
||||||
|
|
||||||
|
WINDOWS_PLATFORM_LIST = \
|
||||||
|
windows-amd64-ui \
|
||||||
windows-amd64-cmd \
|
windows-amd64-cmd \
|
||||||
windows-arm64-cmd
|
windows-arm64-cmd
|
||||||
|
|
||||||
all: $(PLATFORM_LIST) strip
|
all: $(WINDOWS_PLATFORM_LIST) rm_uac $(LINUX_PLATFORM_LIST) strip
|
||||||
|
|
||||||
linux-386-cmd:
|
linux-386-cmd:
|
||||||
GOARCH=386 GOOS=linux $(GOBUILD) -tags "cmd" -o $(BINDIR)/$(NAME)-$@
|
GOARCH=386 GOOS=linux $(GOBUILD) -tags "cmd" -o $(BINDIR)/$(NAME)-$@
|
||||||
@@ -79,9 +81,12 @@ windows-amd64-ui:
|
|||||||
# go build -ldflags -H=windowsgui
|
# go build -ldflags -H=windowsgui
|
||||||
mkdir bin; fyne package; mv *.exe bin/
|
mkdir bin; fyne package; mv *.exe bin/
|
||||||
|
|
||||||
uac:
|
create_uac:
|
||||||
rsrc -manifest nac.manifest -o nac.syso
|
rsrc -manifest nac.manifest -o nac.syso
|
||||||
|
|
||||||
|
rm_uac:
|
||||||
|
rm -rf nac.syso
|
||||||
|
|
||||||
strip:
|
strip:
|
||||||
upx $(BINDIR)/*
|
upx $(BINDIR)/*
|
||||||
|
|
||||||
|
|||||||
26
README.md
26
README.md
@@ -1,10 +1,10 @@
|
|||||||
<img src="https://gitee.com/konyshe/goodlink/raw/master/assert/letter-g-2.png" width="400" height="100">
|
<img src="https://gitee.com/konyshe/goodlink/raw/master/assert/letter-g-2.png" width="400" height="100">
|
||||||
|
|
||||||
由于经常异地办公, 对于市面上的远程桌面工具, 无论速度、画面等, 都不如 windows 自带的远程桌面, 但异地如使用 windows远程桌面呢?
|
由于经常外出办公, 对于市面上的远程桌面工具, 无论画面、适配等, 都不如 windows 自带的远程桌面, 但外出如何使用 windows远程桌面呢?
|
||||||
|
|
||||||
是否可以无需远程桌面, 直接浏览器访问公司的内网 WEB, GIT, SSH 等, 和在公司一模一样?
|
是否可以无需远程桌面, 直接访问公司的内网 WEB, GIT, SSH 等?
|
||||||
|
|
||||||
**注: 该项目仅用于学习研究, 目前没有任何商业合作,更没有任何恶意行为。如果未来有广告之类盈利的行为,会郑重告知大家。另外声明:严禁用于违法行为!!!**
|
**注: 该项目仅用于学习研究, 目前无商业合作,更无恶意行为。如果未来有广告之类盈利的行为,会郑重告知大家。另外声明:严禁用于违法行为!!!**
|
||||||
|
|
||||||
[切换回1.6版文档](https://gitee.com/konyshe/goodlink/blob/v1.6/README.md)
|
[切换回1.6版文档](https://gitee.com/konyshe/goodlink/blob/v1.6/README.md)
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
# 重点
|
# 重点
|
||||||
|
|
||||||
1. 本程序即支持命令行方式, 也支持 docker 方式, windows 平台还增加了UI版本,适合新手
|
1. 本程序即支持命令行方式, 也支持 docker 方式, windows 版本还新增了UI版本, 适合新手。以下举例仅作参考, 可随意搭配
|
||||||
|
|
||||||
2. 两端主机运行同一个程序 / Docker, 一端使用--remote 选项(以下称 remote 端), 另一端使用--local 选项(以下称 local 端)
|
2. 两端主机运行同一个程序 / Docker, 一端使用--remote 选项(以下称 remote 端), 另一端使用--local 选项(以下称 local 端)
|
||||||
|
|
||||||
@@ -32,6 +32,10 @@
|
|||||||
|
|
||||||
7. 以下举例说明中的密钥(--key), 请不要使用, 否则会连上别人的 remote 端, 或者被别人的 local 端连上。自己随机一个 16-24 字节长度的密钥
|
7. 以下举例说明中的密钥(--key), 请不要使用, 否则会连上别人的 remote 端, 或者被别人的 local 端连上。自己随机一个 16-24 字节长度的密钥
|
||||||
|
|
||||||
|
8. 对于有安全疑问,或者想进阶使用的同学,可以看: [使用GoodLink 是否足够安全?](https://gitee.com/konyshe/goodlink/issues/IBFKC2)
|
||||||
|
|
||||||
|
9. 该项目刚刚起步, 可能不太稳定, 欢迎到 Issues 上提出问题和建议, 帮忙测试的同学将保证永久免费使用
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<th>Remote端</th><th>Local端</th><th>P2P成功</th>
|
<th>Remote端</th><th>Local端</th><th>P2P成功</th>
|
||||||
<tr><td>NAT1-3</td><td>NAT1-4</td><td>YES</td></tr>
|
<tr><td>NAT1-3</td><td>NAT1-4</td><td>YES</td></tr>
|
||||||
@@ -47,13 +51,11 @@
|
|||||||
|
|
||||||
Local端会创建一个虚拟网卡, 因此需要管理员权限运行。连接成功后,界面会显示: 对端IP
|
Local端会创建一个虚拟网卡, 因此需要管理员权限运行。连接成功后,界面会显示: 对端IP
|
||||||
|
|
||||||
不限端口,访问对端IP的任意端口,都相当于访问Remote端本机的任意端口
|
不限端口,访问对端IP的任意端口,相当于访问Remote端本机的任意端口
|
||||||
|
|
||||||
对端IP目前固定为: 192.17.19.1 , 具体以界面或者日志显示为准
|
对端IP目前固定为: 192.17.19.1 , 具体以界面或者日志显示为准
|
||||||
|
|
||||||
举例: 在家里电脑(或出差电脑), 打开 windows 远程桌面, 填写对端IP, 即可访问公司电脑的远程桌面
|
举例: 在Local端打开 windows 远程桌面, 填写对端IP, 即可访问Remote端的远程桌面
|
||||||
|
|
||||||
注: 目前仅支持TCP协议, 下一版本将支持UDP协议
|
|
||||||
|
|
||||||
### 代理模式
|
### 代理模式
|
||||||
|
|
||||||
@@ -61,9 +63,7 @@
|
|||||||
|
|
||||||
代理地址端口: socket5://对端IP:1080
|
代理地址端口: socket5://对端IP:1080
|
||||||
|
|
||||||
local端需要在系统或者软件中配置Socket5代理, 访问任意主机端口, 相当于Remote端自己在访问
|
举例: 在Local端配置代理: socks5://对端IP:1080, 即可通过Remote端访问所有的网络资源
|
||||||
|
|
||||||
举例: 在公司电脑上配置代理: socks5://对端IP:1080, 访问家里包括 NAS 在内的所有主机端口
|
|
||||||
|
|
||||||
注: 目前仅支持TCP代理,浏览器可安装插件 SwitchyOmega。其他 GIT, SVN, SSH 等, 都支持socks5代理
|
注: 目前仅支持TCP代理,浏览器可安装插件 SwitchyOmega。其他 GIT, SVN, SSH 等, 都支持socks5代理
|
||||||
|
|
||||||
@@ -93,8 +93,6 @@
|
|||||||
|
|
||||||
#### linux, Docker
|
#### linux, Docker
|
||||||
|
|
||||||
注:2.0版还未提交Docker
|
|
||||||
|
|
||||||
```
|
```
|
||||||
docker rm goodlink -f; docker run -d --name=goodlink --net=host --restart=always registry.cn-shanghai.aliyuncs.com/kony/goodlink --key=nas_202412140928 --remote
|
docker rm goodlink -f; docker run -d --name=goodlink --net=host --restart=always registry.cn-shanghai.aliyuncs.com/kony/goodlink --key=nas_202412140928 --remote
|
||||||
```
|
```
|
||||||
@@ -116,7 +114,7 @@ docker rm goodlink -f; docker run -d --name=goodlink --net=host --restart=always
|
|||||||
#### linux, Docker
|
#### linux, Docker
|
||||||
|
|
||||||
```
|
```
|
||||||
由于Local端需要创建虚拟网卡,Docker中并不支持,因此Local端不支持Docker部署
|
由于Local端需要创建虚拟网卡,Docker中并不支持
|
||||||
```
|
```
|
||||||
|
|
||||||
#### linux, 命令行
|
#### linux, 命令行
|
||||||
|
|||||||
17
netstack/device.go
Normal file
17
netstack/device.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package netstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device is the interface that implemented by network layer devices (e.g. tun),
|
||||||
|
// and easy to use as stack.LinkEndpoint.
|
||||||
|
type Device interface {
|
||||||
|
stack.LinkEndpoint
|
||||||
|
|
||||||
|
// Name returns the current name of the device.
|
||||||
|
Name() string
|
||||||
|
|
||||||
|
// Type returns the driver type of the device.
|
||||||
|
Type() string
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Package iobased provides the implementation of io.ReadWriter
|
//go:build windows
|
||||||
// based data-link layer endpoints.
|
|
||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
80
netstack/setup.go
Normal file
80
netstack/setup.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package netstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/quic-go/quic-go"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setNetStack(s *stack.Stack, nicID tcpip.NICID) error {
|
||||||
|
s.SetRouteTable([]tcpip.Route{
|
||||||
|
{
|
||||||
|
Destination: header.IPv4EmptySubnet,
|
||||||
|
NIC: nicID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := netstack_stack.SetPromiscuousMode(nicID, true); err != nil {
|
||||||
|
return fmt.Errorf("promisc: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := netstack_stack.SetSpoofing(nicID, true); err != nil {
|
||||||
|
return fmt.Errorf("spoofing: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
init_stack_suss = false
|
||||||
|
netstack_stack *stack.Stack
|
||||||
|
)
|
||||||
|
|
||||||
|
func Start() error {
|
||||||
|
if init_stack_suss {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
netstack_stack = stack.New(stack.Options{
|
||||||
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
|
||||||
|
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
|
||||||
|
})
|
||||||
|
|
||||||
|
wintunEP, err := Open(GetName(), 1490) //因为要加自定义头,防止超出1500
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("请管理员权限运行")
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTunIP(&wintunEP, GetRemoteIP(), 32)
|
||||||
|
|
||||||
|
// 将TUN设备注册到协议栈中,使用NIC ID 1
|
||||||
|
nicID := tcpip.NICID(1)
|
||||||
|
if err := netstack_stack.CreateNIC(nicID, wintunEP); err != nil {
|
||||||
|
return fmt.Errorf("设备注册: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
setNetStack(netstack_stack, nicID)
|
||||||
|
|
||||||
|
init_stack_suss = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetForWarder(stun_quic_conn quic.Connection) {
|
||||||
|
netstack_stack.SetTransportProtocolHandler(tcp.ProtocolNumber, NewTcpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
|
||||||
|
netstack_stack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUdpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRemoteIP() string {
|
||||||
|
return "192.17.19.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetName() string {
|
||||||
|
return "GoodLink"
|
||||||
|
}
|
||||||
@@ -3,24 +3,100 @@
|
|||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/quic-go/quic-go"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setupNetstack 初始化并配置网络栈
|
func setUnixIP(name string, ip net.IP, mask net.IPMask) error {
|
||||||
// 该函数负责创建协议栈、设置网络接口、配置IP地址和路由表
|
log.Printf("setUnixIP: %s %s %s", name, ip, mask)
|
||||||
// 返回:
|
|
||||||
// - *stack.Stack: 配置好的网络栈实例
|
// 新增接口存在性检查
|
||||||
// - error: 初始化过程中的错误信息
|
if err := checkInterfaceExists(name); err != nil {
|
||||||
func Start() error {
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改标志位设置流程(先关闭再开启)
|
||||||
|
ifreq, _ := unix.NewIfreq(name)
|
||||||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("SIOCGIFFLAGS(pre-check) failed: %s", unix.ErrnoName(errno))
|
||||||
|
}
|
||||||
|
originalFlags := ifreq.Uint16()
|
||||||
|
|
||||||
|
// 临时关闭接口(关键步骤)
|
||||||
|
ifreq.SetUint16(originalFlags &^ unix.IFF_UP)
|
||||||
|
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("SIOCSIFFLAGS(down) failed: %s", unix.ErrnoName(errno))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置IP地址结构体(修复掩码处理)
|
||||||
|
addr, _ := unix.NewIfreq(name)
|
||||||
|
addr.SetInet4Addr(ip.To4())
|
||||||
|
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFADDR, uintptr(unsafe.Pointer(addr)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("SIOCSIFADDR failed: %s", unix.ErrnoName(errno)) // 显示具体错误名称
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置子网掩码(修复变量名错误)
|
||||||
|
maskAddr, _ := unix.NewIfreq(name)
|
||||||
|
maskAddr.SetInet4Addr(net.IP(mask).To4()) // 显式转换掩码类型
|
||||||
|
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(maskAddr)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("SIOCSIFNETMASK failed: %s", unix.ErrnoName(errno))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改接口激活逻辑(关键修复)
|
||||||
|
ifreq, _ = unix.NewIfreq(name)
|
||||||
|
ifreq.SetUint16((originalFlags | unix.IFF_UP) &^ unix.IFF_NOARP) // 保留原始标志位并添加UP标志
|
||||||
|
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("SIOCSIFFLAGS failed: %s", unix.ErrnoName(errno))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Configuration applied successfully")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetForWarder(stun_quic_conn quic.Connection) {
|
// 新增辅助函数
|
||||||
|
func checkInterfaceExists(name string) error {
|
||||||
|
ifreq, _ := unix.NewIfreq(name)
|
||||||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("interface %s not exists: %s", name, unix.ErrnoName(errno))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRemoteIP() string {
|
// 修改调用端错误处理
|
||||||
return "Linux暂不支持Local端"
|
func SetTunIP(wintunEP *Device, ip string, mask int) error {
|
||||||
}
|
// ip addr add 192.17.0.1/32 dev GoodLink
|
||||||
|
// ip link set GoodLink up
|
||||||
|
// ip route add 192.17.19.1 dev GoodLink
|
||||||
|
|
||||||
func Stop() {
|
// 设置网卡eth0的IP地址为192.168.1.10/24
|
||||||
|
cmd := exec.Command("ip", "addr", "add", "192.17.0.1/32", "dev", GetName())
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command("ip", "link", "set", GetName(), "up")
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command("ip", "route", "add", GetRemoteIP(), "dev", GetName())
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if err := setUnixIP(GetName(), net.ParseIP(ip), net.CIDRMask(mask, 32)); err != nil {
|
||||||
|
return fmt.Errorf("setUnixIP failed: %w", err)
|
||||||
|
}*/
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,17 +11,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetWinTunIP(wintunEP *Device, ip string, mask int) error {
|
func SetTunIP(wintunEP *Device, ip string, mask int) error {
|
||||||
var ipf netip.Prefix
|
var ipf netip.Prefix
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -51,30 +43,6 @@ func SetWinTunIP(wintunEP *Device, ip string, mask int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setNetStack(s *stack.Stack, nicID tcpip.NICID) error {
|
|
||||||
s.SetRouteTable([]tcpip.Route{
|
|
||||||
{
|
|
||||||
Destination: header.IPv4EmptySubnet,
|
|
||||||
NIC: nicID,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := netstack_stack.SetPromiscuousMode(nicID, true); err != nil {
|
|
||||||
return fmt.Errorf("promisc: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := netstack_stack.SetSpoofing(nicID, true); err != nil {
|
|
||||||
return fmt.Errorf("spoofing: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
init_stack_suss = false
|
|
||||||
netstack_stack *stack.Stack
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitWintunDll() error {
|
func InitWintunDll() error {
|
||||||
if gogo.Utils().FileExist("wintun.dll") {
|
if gogo.Utils().FileExist("wintun.dll") {
|
||||||
return nil
|
return nil
|
||||||
@@ -105,48 +73,3 @@ func InitWintunDll() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
tunIP = "192.17.19.1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Start() error {
|
|
||||||
InitWintunDll()
|
|
||||||
|
|
||||||
if init_stack_suss {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
netstack_stack = stack.New(stack.Options{
|
|
||||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
|
|
||||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
|
|
||||||
})
|
|
||||||
|
|
||||||
wintunEP, err := Open("GoodLink", 1490) //因为要加自定义头,防止超出1500
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("请管理员权限运行")
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWinTunIP(&wintunEP, tunIP, 32)
|
|
||||||
|
|
||||||
// 将TUN设备注册到协议栈中,使用NIC ID 1
|
|
||||||
nicID := tcpip.NICID(1)
|
|
||||||
if err := netstack_stack.CreateNIC(nicID, wintunEP); err != nil {
|
|
||||||
return fmt.Errorf("设备注册: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
setNetStack(netstack_stack, nicID)
|
|
||||||
|
|
||||||
init_stack_suss = true
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetForWarder(stun_quic_conn quic.Connection) {
|
|
||||||
netstack_stack.SetTransportProtocolHandler(tcp.ProtocolNumber, NewTcpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
|
|
||||||
netstack_stack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUdpForwarder(netstack_stack, stun_quic_conn).HandlePacket)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRemoteIP() string {
|
|
||||||
return tunIP
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package netstack
|
package netstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
105
netstack/tun_linux.go
Normal file
105
netstack/tun_linux.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package netstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
"gvisor.dev/gvisor/pkg/rawfile"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TUN struct {
|
||||||
|
stack.LinkEndpoint
|
||||||
|
|
||||||
|
fd int
|
||||||
|
mtu uint32
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Open(name string, mtu uint32) (Device, error) {
|
||||||
|
t := &TUN{name: name, mtu: mtu}
|
||||||
|
|
||||||
|
if len(t.name) >= unix.IFNAMSIZ {
|
||||||
|
return nil, fmt.Errorf("interface name too long: %s", t.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := tun.Open(t.name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("create tun: %w", err)
|
||||||
|
}
|
||||||
|
t.fd = fd
|
||||||
|
|
||||||
|
if t.mtu > 0 {
|
||||||
|
if err := setMTU(t.name, t.mtu); err != nil {
|
||||||
|
return nil, fmt.Errorf("set mtu: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_mtu, err := rawfile.GetMTU(t.name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get mtu: %w", err)
|
||||||
|
}
|
||||||
|
t.mtu = _mtu
|
||||||
|
|
||||||
|
ep, err := fdbased.New(&fdbased.Options{
|
||||||
|
FDs: []int{fd},
|
||||||
|
MTU: t.mtu,
|
||||||
|
// TUN only, ignore ethernet header.
|
||||||
|
EthernetHeader: false,
|
||||||
|
// SYS_READV support only for TUN fd.
|
||||||
|
PacketDispatchMode: fdbased.Readv,
|
||||||
|
// TAP/TUN fd's are not sockets and using the WritePackets calls results
|
||||||
|
// in errors as it always defaults to using SendMMsg which is not supported
|
||||||
|
// for tap/tun device fds.
|
||||||
|
//
|
||||||
|
// This CL changes WritePackets to gracefully degrade to using writev instead
|
||||||
|
// of sendmmsg if the underlying fd is not a socket.
|
||||||
|
//
|
||||||
|
// Fixed: https://github.com/google/gvisor/commit/f33d034fecd7723a1e560ccc62aeeba328454fd0
|
||||||
|
MaxSyscallHeaderBytes: 0x00,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("create endpoint: %w", err)
|
||||||
|
}
|
||||||
|
t.LinkEndpoint = ep
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TUN) Name() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TUN) Close() {
|
||||||
|
defer t.LinkEndpoint.Close()
|
||||||
|
_ = unix.Close(t.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TUN) Type() string {
|
||||||
|
return "tun" // 返回固定的设备类型标识符
|
||||||
|
}
|
||||||
|
|
||||||
|
func setMTU(name string, n uint32) error {
|
||||||
|
// open datagram socket
|
||||||
|
fd, err := unix.Socket(
|
||||||
|
unix.AF_INET,
|
||||||
|
unix.SOCK_DGRAM,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer unix.Close(fd)
|
||||||
|
|
||||||
|
ifr, err := unix.NewIfreq(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ifr.SetUint32(n)
|
||||||
|
return unix.IoctlIfreq(fd, unix.SIOCSIFMTU, ifr)
|
||||||
|
}
|
||||||
@@ -10,21 +10,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Device is the interface that implemented by network layer devices (e.g. tun),
|
|
||||||
// and easy to use as stack.LinkEndpoint.
|
|
||||||
type Device interface {
|
|
||||||
stack.LinkEndpoint
|
|
||||||
|
|
||||||
// Name returns the current name of the device.
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// Type returns the driver type of the device.
|
|
||||||
Type() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 常量定义
|
// 常量定义
|
||||||
const (
|
const (
|
||||||
offset = 0 // 数据包偏移量,用于处理TUN_PI头,0表示不使用TUN_PI
|
offset = 0 // 数据包偏移量,用于处理TUN_PI头,0表示不使用TUN_PI
|
||||||
@@ -59,6 +46,8 @@ type TUN struct {
|
|||||||
// - Device: 实现了Device接口的TUN设备
|
// - Device: 实现了Device接口的TUN设备
|
||||||
// - error: 创建过程中的错误信息
|
// - error: 创建过程中的错误信息
|
||||||
func Open(name string, mtu uint32) (_ Device, err error) {
|
func Open(name string, mtu uint32) (_ Device, err error) {
|
||||||
|
InitWintunDll()
|
||||||
|
|
||||||
// 使用defer和recover处理可能的panic,确保错误被正确捕获和包装
|
// 使用defer和recover处理可能的panic,确保错误被正确捕获和包装
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
Reference in New Issue
Block a user