-
Couldn't load subscription status.
- Fork 21
test TCP DNS override on Linux #189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: n2
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a Linux testing tool to test TCP DNS override functionality. The tool creates a new Linux utility that can inject into network namespaces and test DNS-over-HTTPS (DoH) tunneling behavior.
- Implements a TUN interface management tool for testing DNS override
- Adds bridge implementation to integrate with the firestack intra package
- Creates socket pair communication for namespace injection testing
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| linux-tool/toy/main.go | Main testing tool that handles TUN device creation, namespace injection, and DNS tunnel setup |
| linux-tool/glue/glue.go | Bridge implementation providing required interfaces for firestack integration and TUN device utilities |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| func sendTUN(name string) { | ||
| sock := int(3) |
Copilot
AI
Sep 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magic number '3' should be documented or replaced with a named constant to explain why file descriptor 3 is being used.
| func sendTUN(name string) { | |
| sock := int(3) | |
| // SOCKET_FD is the file descriptor number expected to be a socket passed by the parent process. | |
| const SOCKET_FD = 3 | |
| func sendTUN(name string) { | |
| sock := SOCKET_FD |
| return fd, err | ||
| } | ||
| var req [64]byte | ||
| copy(req[:15], []byte(name)) |
Copilot
AI
Sep 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copy operation limits the interface name to 15 bytes, but Linux interface names can be up to 15 characters (IFNAMSIZ-1). If the name is exactly 15 characters, this could cause issues since there's no null termination. Consider using copy(req[:16], []byte(name+"\0")) or validate the name length.
| copy(req[:15], []byte(name)) | |
| if len(name) > 15 { | |
| return -1, syscall.EINVAL | |
| } | |
| copy(req[:16], []byte(name+"\x00")) |
| } | ||
| } | ||
| func OpenTUN(name string) (int, error) { | ||
| fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 600) |
Copilot
AI
Sep 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file mode '600' should use a constant like 0600 for clarity, or better yet, use os.FileMode constants to make the octal permissions explicit.
| fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 600) | |
| fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0600) |
| func (bridge *MyBridge) OnProxiesStopped() {} | ||
|
|
||
| func Ioctl(fd int, req uint64, data []byte) (int, error) { | ||
| p := unsafe.Pointer(&data[0]) |
Check warning
Code scanning / gosec
Use of unsafe calls should be audited Warning
| func GenFDCmsg(fds []uint32) []byte { | ||
| cmsgLen := 16 + len(fds)*4 | ||
| cmsg := make([]byte, cmsgLen) | ||
| binary.NativeEndian.PutUint64(cmsg[:], uint64(cmsgLen)) |
Check failure
Code scanning / gosec
integer overflow conversion uint64 -> uint32 Error
| func sendTUN(name string) { | ||
| sock := int(3) | ||
| defer syscall.Close(sock) | ||
| syscall.SetNonblock(sock, true) |
Check warning
Code scanning / gosec
Errors unhandled Warning
| ifInfo, err := net.InterfaceByName(name) | ||
| p(err) | ||
| var msg [4]byte | ||
| binary.NativeEndian.PutUint32(msg[:], uint32(ifInfo.MTU)) |
Check failure
Code scanning / gosec
integer overflow conversion uint64 -> uint32 Error
| p(err) | ||
| var msg [4]byte | ||
| binary.NativeEndian.PutUint32(msg[:], uint32(ifInfo.MTU)) | ||
| cmsg := glue.GenFDCmsg([]uint32{uint32(tun)}) |
Check failure
Code scanning / gosec
integer overflow conversion uint64 -> uint32 Error
| pair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0) | ||
| p(err) | ||
| defer func() { | ||
| syscall.Close(pair[0]) |
Check warning
Code scanning / gosec
Errors unhandled Warning
| p(err) | ||
| defer func() { | ||
| syscall.Close(pair[0]) | ||
| syscall.Close(pair[1]) |
Check warning
Code scanning / gosec
Errors unhandled Warning
| syscall.Close(pair[0]) | ||
| syscall.Close(pair[1]) | ||
| }() | ||
| syscall.SetNonblock(pair[0], true) |
Check warning
Code scanning / gosec
Errors unhandled Warning
| c1 := exec.Command("/usr/bin/nsenter", "--target", fmt.Sprintf("%d", targetPid), "--user", "--net", | ||
| "--preserve-credentials", "--keep-caps", | ||
| elfPath, "-mode", "sendfd", "-tun", tunName) |
Check failure
Code scanning / gosec
Subprocess launched with a potential tainted input or cmd arguments Error
#77 (comment)