Last active
July 27, 2020 09:21
-
-
Save optman/8055431d42d3b530dcbf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"net" | |
"strconv" | |
"syscall" | |
"unsafe" | |
"os" | |
) | |
type sockaddr struct { | |
family uint16 | |
data [14]byte | |
} | |
const SO_ORIGINAL_DST = 80 | |
func getTCPConnFd(conn *net.Conn)(*os.File, error){ | |
tcpConn, ok := (*conn).(*net.TCPConn) | |
if !ok { | |
return nil, errors.New("not a TCPConn") | |
} | |
file, err := tcpConn.File() | |
if err != nil { | |
return nil, err | |
} | |
// To avoid potential problems from making the socket non-blocking. | |
/* | |
tcpConn.Close() | |
*conn, err = net.FileConn(file) | |
if err != nil { | |
return nil, err | |
}*/ | |
return file, nil | |
} | |
func getUDPConnFd(conn *net.Conn)(*os.File, error){ | |
udpConn, ok := (*conn).(*net.UDPConn) | |
if !ok { | |
return nil, errors.New("not a UDPConn") | |
} | |
return udpConn.File() | |
} | |
func realTcpAddress(tcpConn *net.TCPConn) (string, error) { | |
var conn net.Conn | |
conn = tcpConn | |
file, err := getTCPConnFd(&conn) | |
if err != nil{ | |
return "", err | |
} | |
defer file.Close() | |
fd := file.Fd() | |
var addr sockaddr | |
size := uint32(unsafe.Sizeof(addr)) | |
err = getsockopt(int(fd), syscall.SOL_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&addr)), &size) | |
if err != nil { | |
return "", err | |
} | |
var ip net.IP | |
switch addr.family { | |
case syscall.AF_INET: | |
ip = addr.data[2:6] | |
default: | |
return "", errors.New("unrecognized address family") | |
} | |
port := int(addr.data[0])<<8 + int(addr.data[1]) | |
return net.JoinHostPort(ip.String(), strconv.Itoa(port)), nil | |
} | |
func setRecvOrigDstAddr(udpConn *net.UDPConn)error{ | |
var conn net.Conn | |
conn = udpConn | |
file, err := getUDPConnFd(&conn) | |
if err != nil{ | |
return err | |
} | |
defer file.Close() | |
fd := file.Fd() | |
opt := uint32(1) | |
size := uint32(4) | |
err = setsockopt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, uintptr(unsafe.Pointer(&opt)), size) | |
err = setsockopt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, uintptr(unsafe.Pointer(&opt)), size) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func getsockopt(s int, level int, name int, val uintptr, vallen *uint32) (err error) { | |
_, _, e1 := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) | |
if e1 != 0 { | |
err = e1 | |
} | |
return | |
} | |
func setsockopt(s int, level int, name int, val uintptr, vallen uint32) (err error) { | |
_, _, e1 := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) | |
if e1 != 0 { | |
err = e1 | |
} | |
return | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func listenudp() { | |
udpAddr, _ := net.ResolveUDPAddr("udp", CONN_HOST+":"+CONN_PORT) | |
udpConn, err := net.ListenUDP("udp", udpAddr) | |
if err != nil { | |
fmt.Println("Error listening udp:", err.Error()) | |
os.Exit(1) | |
} | |
err = setRecvOrigDstAddr(udpConn) | |
if err != nil{ | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
defer udpConn.Close() | |
fmt.Println("udp listening on " + CONN_HOST + ":" + CONN_PORT) | |
for { | |
data := make([]byte, 1600) | |
oob := make([]byte, 1600) | |
n, oobn, flags, srcAddr, err := udpConn.ReadMsgUDP(data, oob) | |
if err != nil{ | |
fmt.Println("ReadMSGUDP fail!", err) | |
os.Exit(1) | |
} | |
log.Println("read udp data from", srcAddr, "data", n, | |
"oob", oobn, "flags", flags) | |
cmsgs, err := syscall.ParseSocketControlMessage(oob[:oobn]) | |
if err == nil{ | |
for _, cmsg := range cmsgs{ | |
if cmsg.Header.Level == syscall.SOL_IP && | |
cmsg.Header.Type == syscall.IP_ORIGDSTADDR{ | |
//log.Println(cmsg.Data) | |
var ip net.IP | |
ip = cmsg.Data[4:8] | |
port := int(cmsg.Data[2])<<8 + int(cmsg.Data[3]) | |
fmt.Printf("original dst: %s:%d\n", ip, port) | |
} | |
} | |
} | |
//log.Println(oob[:oobn], cmsg) | |
} | |
} | |
func listentcp() { | |
l, err := net.Listen("tcp", CONN_HOST+":"+CONN_PORT) | |
if err != nil { | |
fmt.Println("Error listening tcp:", err.Error()) | |
os.Exit(1) | |
} | |
defer l.Close() | |
fmt.Println("tcp listening on " + CONN_HOST + ":" + CONN_PORT) | |
for { | |
conn, err := l.Accept() | |
if err != nil { | |
fmt.Println("Error accepting: ", err.Error()) | |
os.Exit(1) | |
} | |
tcpConn, _ := conn.(*net.TCPConn) | |
go handleTcpRequest(tcpConn) | |
} | |
} |
tcp intercept can use REDIRECT instead of TPROXY.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
reference:
http://play.golang.org/p/GMAaKucHOr