├── Driver.c ├── Driver.go ├── Driver.h ├── ProcessInfo.go ├── Socks5.go ├── Socks5Map.go ├── Sokcs.go ├── TcpMap.go ├── core ├── cipher.go ├── doc.go ├── packet.go └── stream.go ├── dns.go ├── include ├── nfapi.h ├── nfdriver.h └── nfevents.h ├── lib ├── nfapi.exp └── nfapi.lib ├── main.go ├── shadowaead ├── cipher.go ├── doc.go ├── packet.go └── stream.go ├── shadowstream ├── cipher.go ├── doc.go ├── packet.go └── stream.go ├── tcp.go └── udp.go /Driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Driver.h" 3 | #include "nfapi.h" 4 | 5 | #include 6 | 7 | 8 | int inet_pton(int af, const char *csrc, void *dst) 9 | { 10 | char * src; 11 | 12 | if (csrc == NULL || (src = strdup(csrc)) == NULL) { 13 | return 0; 14 | } 15 | 16 | switch (af) { 17 | case AF_INET: 18 | { 19 | struct sockaddr_in si4; 20 | INT r; 21 | INT s = sizeof(si4); 22 | 23 | si4.sin_family = AF_INET; 24 | r = WSAStringToAddress(src, AF_INET, NULL, (LPSOCKADDR) &si4, &s); 25 | free(src); 26 | src = NULL; 27 | 28 | if (r == 0) { 29 | memcpy(dst, &si4.sin_addr, sizeof(si4.sin_addr)); 30 | return 1; 31 | } 32 | } 33 | break; 34 | 35 | case AF_INET6: 36 | { 37 | struct sockaddr_in6 si6; 38 | INT r; 39 | INT s = sizeof(si6); 40 | 41 | si6.sin6_family = AF_INET6; 42 | r = WSAStringToAddress(src, AF_INET6, NULL, (LPSOCKADDR) &si6, &s); 43 | free(src); 44 | src = NULL; 45 | 46 | if (r == 0) { 47 | memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr)); 48 | return 1; 49 | } 50 | } 51 | break; 52 | 53 | default: 54 | return -1; 55 | } 56 | 57 | { 58 | int le = WSAGetLastError(); 59 | 60 | if (le == WSAEINVAL) 61 | return 0; 62 | 63 | return -1; 64 | } 65 | } 66 | 67 | 68 | 69 | 70 | //netfilter2 71 | 72 | #define NFDRIVER_NAME "netfilter2" 73 | 74 | //C调Golang函数 75 | extern void go_threadStart(); 76 | extern void go_threadEnd(); 77 | extern void go_tcpConnectRequest(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 78 | extern void go_tcpConnected(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 79 | extern void go_tcpClosed(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 80 | extern void go_tcpReceive(ENDPOINT_ID id, const char * buf, int len); 81 | extern void go_tcpSend(ENDPOINT_ID id, const char * buf, int len); 82 | extern void go_tcpCanReceive(ENDPOINT_ID id); 83 | extern void go_tcpCanSend(ENDPOINT_ID id); 84 | extern void go_udpCreated(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 85 | extern void go_udpConnectRequest(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnReq); 86 | extern void go_udpClosed(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 87 | extern void go_udpReceive(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 88 | extern void go_udpSend(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 89 | extern void go_udpCanReceive(ENDPOINT_ID id); 90 | extern void go_udpCanSend(ENDPOINT_ID id); 91 | 92 | 93 | 94 | 95 | void threadStart(){ 96 | go_threadStart(); 97 | } 98 | void threadEnd(){ 99 | go_threadEnd(); 100 | } 101 | void tcpConnectRequest(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo){ 102 | go_tcpConnectRequest(id,pConnInfo); 103 | } 104 | void tcpConnected(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo){ 105 | go_tcpConnected(id,pConnInfo); 106 | } 107 | void tcpClosed(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo){ 108 | go_tcpClosed(id,pConnInfo); 109 | } 110 | void tcpReceive(ENDPOINT_ID id, const char * buf, int len){ 111 | go_tcpReceive(id,buf,len); 112 | } 113 | void tcpSend(ENDPOINT_ID id, const char * buf, int len){ 114 | go_tcpSend(id,buf,len); 115 | } 116 | void tcpCanReceive(ENDPOINT_ID id){ 117 | go_tcpCanReceive(id); 118 | } 119 | void tcpCanSend(ENDPOINT_ID id){ 120 | go_tcpCanSend(id); 121 | } 122 | void udpCreated(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo){ 123 | go_udpCreated(id,pConnInfo); 124 | } 125 | void udpConnectRequest(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnReq){ 126 | go_udpConnectRequest(id,pConnReq); 127 | } 128 | void udpClosed(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo){ 129 | go_udpClosed(id,pConnInfo); 130 | } 131 | void udpReceive(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options){ 132 | go_udpReceive(id,remoteAddress,buf,len,options); 133 | } 134 | void udpSend(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options){ 135 | go_udpSend(id,remoteAddress,buf,len,options); 136 | } 137 | void udpCanReceive(ENDPOINT_ID id){ 138 | go_udpCanReceive(id); 139 | } 140 | void udpCanSend(ENDPOINT_ID id){ 141 | go_udpCanSend(id); 142 | } 143 | 144 | 145 | //////////////////////////////////控制程序//////////////////////////////// 146 | 147 | NF_EventHandler eh = { 148 | threadStart, 149 | threadEnd, 150 | tcpConnectRequest, 151 | tcpConnected, 152 | tcpClosed, 153 | tcpReceive, 154 | tcpSend, 155 | tcpCanReceive, 156 | tcpCanSend, 157 | udpCreated, 158 | udpConnectRequest, 159 | udpClosed, 160 | udpReceive, 161 | udpSend, 162 | udpCanReceive, 163 | udpCanSend 164 | }; 165 | 166 | void DriverFree () { 167 | nf_deleteRules (); 168 | nf_free(); 169 | } 170 | 171 | int DriverMain(){ 172 | return nf_init(NFDRIVER_NAME, &eh); 173 | } 174 | 175 | 176 | int cPort = 0; 177 | char * c4addr = ""; 178 | char * c6addr = ""; 179 | 180 | 181 | void setPort(int a,char * b,char * c){ 182 | 183 | cPort = a; 184 | c4addr = b; 185 | c6addr = c; 186 | } 187 | 188 | 189 | void setAddrV4(void *ppDetectInfo) 190 | { 191 | struct sockaddr_in addr; 192 | memset(&addr, 0, sizeof(addr)); 193 | addr.sin_family = AF_INET; 194 | addr.sin_addr.s_addr = inet_addr(c4addr); 195 | addr.sin_port = htons(cPort); 196 | 197 | memcpy(ppDetectInfo, &addr, sizeof(addr)); 198 | } 199 | 200 | void setAddrV6(void *ppDetectInfo) 201 | { 202 | struct sockaddr_in6 addr; 203 | memset(&addr, 0, sizeof(addr)); 204 | addr.sin6_family = AF_INET6; 205 | inet_pton(AF_INET6, c6addr,&addr.sin6_addr); 206 | addr.sin6_port = htons(cPort); 207 | 208 | memcpy(ppDetectInfo, &addr, sizeof(addr)); 209 | } -------------------------------------------------------------------------------- /Driver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo LDFLAGS: -lwsock32 5 | #cgo LDFLAGS: -lWs2_32 6 | #cgo CFLAGS: -I ./include 7 | #cgo LDFLAGS: -L ./lib -lnfapi 8 | 9 | #include 10 | #include 11 | #include "nfapi.h" 12 | #include "Driver.h" 13 | */ 14 | import "C" 15 | 16 | import ( 17 | "strconv" 18 | "strings" 19 | "sync" 20 | "syscall" 21 | "unsafe" 22 | ) 23 | 24 | var uMap sync.Map 25 | 26 | //void (NFAPI_CC *threadStart)(); 27 | //export go_threadStart 28 | func go_threadStart() { 29 | 30 | } 31 | 32 | //void (NFAPI_CC *threadEnd)(); 33 | //export go_threadEnd 34 | func go_threadEnd() { 35 | 36 | } 37 | 38 | //void (NFAPI_CC *tcpConnectRequest)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 39 | //export go_tcpConnectRequest 40 | func go_tcpConnectRequest(id C.ENDPOINT_ID, pConnInfo C.PNF_TCP_CONN_INFO) { 41 | 42 | //查找进程是否需要代理 43 | prs, ok := proxyMap.Load(uint64(pConnInfo.processId)) 44 | if !ok { 45 | return 46 | } 47 | m, ok := prs.(ProxyInfo) 48 | if !ok { 49 | return 50 | } 51 | 52 | //查询进程ID是否开启了UDP代理 1为代理 TCP 2为代理 UDP 3为 代理TCP+UDP 53 | 54 | if m.proxymode == 2 { 55 | return 56 | } 57 | 58 | //取出本地地址 59 | plAddr, err := (*syscall.RawSockaddrAny)(unsafe.Pointer(&(pConnInfo.localAddress))).Sockaddr() 60 | if err != nil { 61 | return 62 | } 63 | //取出远程地址 64 | prAddr, err := (*syscall.RawSockaddrAny)(unsafe.Pointer(&(pConnInfo.remoteAddress))).Sockaddr() 65 | if err != nil { 66 | return 67 | } 68 | //取本地端口 69 | var k int 70 | if laddrV4, ok := plAddr.(*syscall.SockaddrInet4); ok { 71 | k = laddrV4.Port 72 | } else if laddrV6, ok := plAddr.(*syscall.SockaddrInet6); ok { 73 | k = laddrV6.Port 74 | } 75 | 76 | var rom []byte 77 | if raddrV4, ok := prAddr.(*syscall.SockaddrInet4); ok { 78 | 79 | p := Htons(uint16(raddrV4.Port)) 80 | ta := append([]byte{1}, raddrV4.Addr[:]...) 81 | rom = append(ta, p[:]...) 82 | 83 | tcpmap.Set(k, uint64(pConnInfo.processId), rom) 84 | 85 | C.setAddrV4(unsafe.Pointer(&(pConnInfo.remoteAddress))) 86 | 87 | } else if raddrV6, ok := prAddr.(*syscall.SockaddrInet6); ok { 88 | 89 | p := Htons(uint16(raddrV6.Port)) 90 | ta := append([]byte{4}, raddrV6.Addr[:]...) 91 | rom = append(ta, p[:]...) 92 | 93 | tcpmap.Set(k, uint64(pConnInfo.processId), rom) 94 | C.setAddrV6(unsafe.Pointer(&(pConnInfo.remoteAddress))) 95 | } 96 | 97 | } 98 | 99 | //void (NFAPI_CC *tcpConnected)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 100 | //export go_tcpConnected 101 | func go_tcpConnected(id C.ENDPOINT_ID, pConnInfo C.PNF_TCP_CONN_INFO) { 102 | 103 | } 104 | 105 | //void (NFAPI_CC *tcpClosed)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 106 | //export go_tcpClosed 107 | func go_tcpClosed(id C.ENDPOINT_ID, pConnInfo C.PNF_TCP_CONN_INFO) { 108 | 109 | } 110 | 111 | //void (NFAPI_CC *tcpReceive)(ENDPOINT_ID id, const char * buf, int len); 112 | //export go_tcpReceive 113 | func go_tcpReceive(id C.ENDPOINT_ID, buf *C.char, len C.int) { 114 | 115 | } 116 | 117 | //void (NFAPI_CC *tcpSend)(ENDPOINT_ID id, const char * buf, int len); 118 | //export go_tcpSend 119 | func go_tcpSend(id C.ENDPOINT_ID, buf *C.char, len C.int) { 120 | 121 | } 122 | 123 | //void (NFAPI_CC *tcpCanReceive)(ENDPOINT_ID id); 124 | //export go_tcpCanReceive 125 | func go_tcpCanReceive(id C.ENDPOINT_ID) { 126 | 127 | } 128 | 129 | //void (NFAPI_CC *tcpCanSend)(ENDPOINT_ID id); 130 | //export go_tcpCanSend 131 | func go_tcpCanSend(id C.ENDPOINT_ID) { 132 | 133 | } 134 | 135 | //void (NFAPI_CC *udpCreated)(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 136 | //export go_udpCreated 137 | func go_udpCreated(id C.ENDPOINT_ID, pConnInfo C.PNF_UDP_CONN_INFO) { 138 | 139 | //进程id 140 | prid := uint64(pConnInfo.processId) 141 | 142 | //查找进程id是否在代理列表中 143 | prs, ok := proxyMap.Load(prid) 144 | if !ok { 145 | return 146 | } 147 | m, ok := prs.(ProxyInfo) 148 | if !ok { 149 | return 150 | } 151 | 152 | //查询进程ID是否开启了UDP代理 1为代理 TCP 2为代理 UDP 3为 代理TCP+UDP 153 | if m.proxymode == 1 { 154 | return 155 | } 156 | 157 | uMap.Store(id, prid) 158 | 159 | //socks5需要tcp请求开发端口 160 | if m.ptype == AtypSocks5 { 161 | go sockHandler(id, m.ip, m.port, m.user, m.passw, m.socks) 162 | } 163 | 164 | } 165 | 166 | func sockHandler(id C.ENDPOINT_ID, ip string, port int, user string, pass string, smap *suMap) { 167 | 168 | //a, b, err := SocksUDPHandshake(ip, port, user, pass) 169 | a, b, err := Socks5Udp(ip, port, user, pass) 170 | if err != nil { 171 | return 172 | } 173 | 174 | smap.Set(int64(id), b, a) 175 | } 176 | 177 | //void (NFAPI_CC *udpConnectRequest)(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnReq); 178 | //export go_udpConnectRequest 179 | func go_udpConnectRequest(id C.ENDPOINT_ID, pConnReq C.PNF_UDP_CONN_REQUEST) { 180 | 181 | } 182 | 183 | //void (NFAPI_CC *udpClosed)(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 184 | //export go_udpClosed 185 | func go_udpClosed(id C.ENDPOINT_ID, pConnInfo C.PNF_UDP_CONN_INFO) { 186 | 187 | //查找进程id是否在代理列表中 188 | prs, ok := proxyMap.Load(uint64(pConnInfo.processId)) 189 | if !ok { 190 | return 191 | } 192 | m, ok := prs.(ProxyInfo) 193 | if !ok { 194 | return 195 | } 196 | 197 | //关掉socks5的握手请求 198 | if m.ptype == AtypSocks5 { 199 | m.socks.Del(int64(id)) 200 | } 201 | 202 | uMap.Delete(id) 203 | } 204 | 205 | //void (NFAPI_CC *udpReceive)(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 206 | //export go_udpReceive 207 | func go_udpReceive(id C.ENDPOINT_ID, remoteAddress *C.uchar, buf *C.char, len C.int, options C.PNF_UDP_OPTIONS) { 208 | 209 | C.nf_udpPostReceive(id, remoteAddress, buf, len, options) 210 | 211 | } 212 | 213 | //void (NFAPI_CC *udpSend)(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 214 | //export go_udpSend 215 | func go_udpSend(id C.ENDPOINT_ID, remoteAddress *C.uchar, buf *C.char, len C.int, options C.PNF_UDP_OPTIONS) { 216 | 217 | //取出远程地址 218 | prAddr, err := (*syscall.RawSockaddrAny)(unsafe.Pointer(remoteAddress)).Sockaddr() 219 | if err != nil { 220 | return 221 | } 222 | 223 | var IP []byte 224 | var PORT [2]byte 225 | var IPTYPE int 226 | //取出数据包内容 227 | abuf := (*[1 << 30]byte)(unsafe.Pointer(buf))[:int(len)] 228 | var BUFF = make([]byte, int(len)) 229 | copy(BUFF[:], abuf[:]) 230 | 231 | if raddrV4, ok := prAddr.(*syscall.SockaddrInet4); ok { 232 | IPTYPE = AtypIPv4 233 | IP = raddrV4.Addr[:] 234 | PORT = Htons(uint16(raddrV4.Port)) 235 | } else if raddrV6, ok := prAddr.(*syscall.SockaddrInet6); ok { 236 | IPTYPE = AtypIPv6 237 | IP = raddrV6.Addr[:] 238 | PORT = Htons(uint16(raddrV6.Port)) 239 | } else { 240 | return 241 | } 242 | 243 | //DNS 244 | if PORT == [2]byte{0, 53} { 245 | if DnsAddr != nil { 246 | //DNS 请求 247 | go DNSRequest(id, remoteAddress, BUFF, options) 248 | return 249 | } 250 | 251 | } 252 | 253 | //判断id是否需要代理转发 254 | if pid, ok := uMap.Load(id); ok { 255 | 256 | if v, ook := pid.(uint64); ook { 257 | SendTo(id, v, IPTYPE, IP, PORT[:], BUFF, options, int(len)) 258 | } 259 | return 260 | } 261 | 262 | C.nf_udpPostSend(id, remoteAddress, buf, len, options) 263 | } 264 | 265 | //void (NFAPI_CC *udpCanReceive)(ENDPOINT_ID id); 266 | //export go_udpCanReceive 267 | func go_udpCanReceive(id C.ENDPOINT_ID) { 268 | 269 | } 270 | 271 | //void (NFAPI_CC *udpCanSend)(ENDPOINT_ID id); 272 | //export go_udpCanSend 273 | func go_udpCanSend(id C.ENDPOINT_ID) { 274 | 275 | } 276 | 277 | //****************************************************** 278 | 279 | func DriverInit() C.int { 280 | 281 | return C.DriverMain() 282 | } 283 | 284 | func DriverFree() bool { 285 | 286 | C.nf_deleteRules() 287 | C.nf_free() 288 | 289 | return true 290 | } 291 | 292 | //******************************** 293 | func Htons(data uint16) (ret [2]byte) { 294 | ret[0] = byte((data >> 8) & 0xff) 295 | ret[1] = byte((data >> 0) & 0xff) 296 | return 297 | } 298 | 299 | func inet_addr(ipaddr string) [4]byte { 300 | var ( 301 | ips = strings.Split(ipaddr, ".") 302 | ip [4]uint64 303 | ret [4]byte 304 | ) 305 | for i := 0; i < 4; i++ { 306 | ip[i], _ = strconv.ParseUint(ips[i], 10, 8) 307 | } 308 | for i := 0; i < 4; i++ { 309 | ret[i] = byte(ip[i]) 310 | } 311 | return ret 312 | } 313 | 314 | func Int2Byte(data int) (ret []byte) { 315 | var len uintptr = unsafe.Sizeof(data) 316 | ret = make([]byte, len) 317 | var tmp int = 0xff 318 | var index uint = 0 319 | for index = 0; index < uint(len); index++ { 320 | ret[index] = byte((tmp << (index * 8) & data) >> (index * 8)) 321 | } 322 | return ret 323 | } 324 | 325 | //构建UDP的请求包 326 | func UDPByte(iptype int, ip []byte, port []byte, buf []byte, bufflen int, AType int) []byte { 327 | 328 | if iptype == AtypIPv4 { 329 | 330 | var buff = make([]byte, bufflen+7) 331 | 332 | buff[0] = AtypIPv4 333 | copy(buff[1:], ip[:4]) 334 | copy(buff[5:], port[:2]) 335 | copy(buff[7:], buf[:bufflen]) 336 | 337 | //Socks5协议 添加额外请求头 338 | if AType == AtypSocks5 { 339 | var RetBuff = make([]byte, bufflen+7+3) 340 | copy(RetBuff[:2], []byte{0, 0, 0}) 341 | copy(RetBuff[3:], buff[:bufflen+7]) 342 | return RetBuff 343 | } 344 | 345 | return buff 346 | 347 | } else if iptype == AtypIPv6 { 348 | 349 | var buff = make([]byte, bufflen+19) 350 | 351 | buff[0] = AtypIPv6 352 | copy(buff[1:], ip[:]) 353 | copy(buff[17:], port[:]) 354 | copy(buff[19:], buf[:]) 355 | 356 | //Socks5协议 添加额外请求头 357 | if AType == AtypSocks5 { 358 | var RetBuff = make([]byte, bufflen+19+3) 359 | copy(RetBuff[:2], []byte{0, 0, 0}) 360 | copy(RetBuff[3:], buff[:]) 361 | return RetBuff 362 | } 363 | 364 | return buff 365 | } 366 | 367 | return nil 368 | } 369 | -------------------------------------------------------------------------------- /Driver.h: -------------------------------------------------------------------------------- 1 | //Driver.h 2 | int DriverMain(); 3 | void setPort(int a,char * b,char * c); 4 | void setAddrV4(void *p); 5 | void setAddrV6(void *p); -------------------------------------------------------------------------------- /ProcessInfo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | /* 8 | 此Map用于储存进程的流量信息 9 | 10 | key为进程id 11 | */ 12 | 13 | type mMap struct { 14 | Map map[uint64]mInfo 15 | lock *sync.RWMutex // 加锁 16 | } 17 | 18 | type mInfo struct { 19 | send int64 //发送量 20 | recv int64 //接收量 21 | } 22 | 23 | func NewProcessMap() *mMap { 24 | return &mMap{Map: make(map[uint64]mInfo), lock: new(sync.RWMutex)} 25 | } 26 | 27 | // 添加流量统计 28 | func (m *mMap) Add(key uint64, send int64, recv int64) { 29 | m.lock.Lock() 30 | defer m.lock.Unlock() 31 | 32 | c := m.Map[key] 33 | m.Map[key] = mInfo{send: c.send + send, recv: c.recv + recv} 34 | 35 | } 36 | 37 | //Del 38 | func (m *mMap) Del(key uint64) { 39 | m.lock.Lock() 40 | defer m.lock.Unlock() 41 | delete(m.Map, key) 42 | } 43 | 44 | // Get ... 45 | func (m *mMap) Get(key uint64) mInfo { 46 | m.lock.Lock() 47 | defer m.lock.Unlock() 48 | return m.Map[key] 49 | } 50 | -------------------------------------------------------------------------------- /Socks5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net" 8 | "strconv" 9 | "time" 10 | ) 11 | 12 | func SocksHandle(conn net.Conn, ip []byte) (err error) { 13 | 14 | buf := append([]byte{5, 1, 0}, ip...) 15 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 16 | _, err = conn.Write(buf[:]) 17 | if err != nil { 18 | return 19 | } 20 | var resp [2]byte 21 | 22 | conn.SetReadDeadline(time.Now().Add(time.Second)) 23 | r := bufio.NewReader(conn) 24 | _, err = io.ReadFull(r, resp[:2]) 25 | 26 | if err != nil { 27 | return 28 | } 29 | 30 | if resp[1] != 0x00 { 31 | 32 | return fmt.Errorf("err", err) 33 | } 34 | conn.SetDeadline(time.Time{}) 35 | 36 | return 37 | } 38 | 39 | func Socks5Tcp(conn net.Conn, user, pass string, ip []byte) (err error) { 40 | 41 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 42 | var req [4]byte 43 | req[0] = 5 44 | req[1] = 2 45 | req[2] = 0 46 | req[3] = 2 47 | _, err = conn.Write(req[:]) 48 | if err != nil { 49 | return 50 | } 51 | 52 | conn.SetReadDeadline(time.Now().Add(time.Second)) 53 | // 接收服务器应答 54 | var resp [2]byte 55 | r := bufio.NewReader(conn) 56 | _, err = io.ReadFull(r, resp[:2]) 57 | 58 | if err != nil { 59 | return 60 | } 61 | // 不需要密码 验证通过 62 | if resp[1] == 0x00 { 63 | 64 | return SocksHandle(conn, ip) 65 | } 66 | 67 | // 构建用户名密码数据包 68 | b := make([]byte, 513) 69 | b[0] = 0x01 70 | uLen := len(user) 71 | b[1] = byte(uLen) 72 | idx := 2 + uLen 73 | copy(b[2:idx], user) 74 | 75 | pLen := len(pass) 76 | b[idx] = byte(pLen) 77 | idx++ 78 | copy(b[idx:idx+pLen], pass) 79 | idx += pLen 80 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 81 | if _, err = conn.Write(b[:idx]); err != nil { 82 | return 83 | } 84 | 85 | // 设置接收数据超时 86 | conn.SetReadDeadline(time.Now().Add(time.Second)) 87 | // 接收服务器应答 88 | r = bufio.NewReader(conn) 89 | 90 | if _, err = io.ReadFull(r, resp[:2]); err != nil { 91 | return 92 | } 93 | // 服务器校验认证错误 94 | if resp[0] != 0x01 { 95 | return fmt.Errorf("err", err) 96 | } 97 | 98 | return SocksHandle(conn, ip) 99 | } 100 | 101 | func Socks5Udp(ip string, port int, user, pass string) (addr net.Addr, c net.Conn, err error) { 102 | 103 | server := ip + ":" + strconv.Itoa(port) 104 | 105 | conn, err := net.Dial("tcp", server) 106 | if err != nil { 107 | return 108 | } 109 | 110 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 111 | var req [4]byte 112 | req[0] = 5 113 | req[1] = 2 114 | req[2] = 0 115 | req[3] = 2 116 | _, err = conn.Write(req[:]) 117 | if err != nil { 118 | return 119 | } 120 | 121 | conn.SetReadDeadline(time.Now().Add(time.Second)) 122 | // 接收服务器应答 123 | var resp [2]byte 124 | r := bufio.NewReader(conn) 125 | _, err = io.ReadFull(r, resp[:2]) 126 | if err != nil { 127 | return 128 | } 129 | 130 | // 不需要密码 验证通过 131 | if resp[1] == 0x00 { 132 | return Udphandle(conn, ip) 133 | } 134 | 135 | // 构建用户名密码数据包 136 | b := make([]byte, 513) 137 | b[0] = 0x01 138 | uLen := len(user) 139 | b[1] = byte(uLen) 140 | idx := 2 + uLen 141 | copy(b[2:idx], user) 142 | 143 | pLen := len(pass) 144 | b[idx] = byte(pLen) 145 | idx++ 146 | copy(b[idx:idx+pLen], pass) 147 | idx += pLen 148 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 149 | if _, err = conn.Write(b[:idx]); err != nil { 150 | return 151 | } 152 | 153 | // 设置接收数据超时 154 | conn.SetReadDeadline(time.Now().Add(time.Second)) 155 | // 接收服务器应答 156 | r = bufio.NewReader(conn) 157 | 158 | if _, err = io.ReadFull(r, resp[:2]); err != nil { 159 | return 160 | } 161 | // 服务器校验认证错误 162 | if resp[1] != 0x00 { 163 | err = fmt.Errorf("err") 164 | return 165 | 166 | } 167 | 168 | return Udphandle(conn, ip) 169 | 170 | } 171 | 172 | func Udphandle(conn net.Conn, ip string) (addr net.Addr, c net.Conn, err error) { 173 | 174 | buf := []byte{5, 3, 0, 1, 0, 0, 0, 0, 0, 0} 175 | conn.SetWriteDeadline(time.Now().Add(time.Second)) 176 | _, err = conn.Write(buf[:]) 177 | if err != nil { 178 | return 179 | } 180 | var resp [10]byte 181 | conn.SetReadDeadline(time.Now().Add(time.Second)) 182 | r := bufio.NewReader(conn) 183 | _, err = io.ReadFull(r, resp[:10]) 184 | if err != nil { 185 | return 186 | } 187 | 188 | if resp[1] != 0x00 { 189 | 190 | return nil, nil, fmt.Errorf("err", err) 191 | } 192 | //{5,0,0,1,172,16,0,5,207,171} 193 | 194 | m := strconv.Itoa((int(resp[8]) << 8) | int(resp[9])) 195 | srvAddr, err := net.ResolveUDPAddr("udp", ip+":"+m) 196 | if err != nil { 197 | return 198 | } 199 | 200 | conn.SetDeadline(time.Time{}) 201 | return srvAddr, conn, nil 202 | 203 | } 204 | -------------------------------------------------------------------------------- /Socks5Map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | ) 7 | 8 | /* 9 | 此map用于保存socks5udp的我受请求和握手端口 10 | key 为驱动id 11 | 12 | */ 13 | type su struct { 14 | conn net.Conn //UDP的握手请求 15 | server net.Addr // server地址 16 | } 17 | 18 | // socks5UdpMap 19 | type suMap struct { 20 | Map map[int64]su 21 | lock *sync.RWMutex // 加锁 22 | } 23 | 24 | func NewSuMap() *suMap { 25 | return &suMap{Map: make(map[int64]su), lock: new(sync.RWMutex)} 26 | } 27 | 28 | // Set ... 29 | func (m *suMap) Set(key int64, conn net.Conn, server net.Addr) { 30 | m.lock.Lock() 31 | defer m.lock.Unlock() 32 | m.Map[key] = su{conn: conn, server: server} 33 | } 34 | 35 | //Del 36 | func (m *suMap) Del(key int64) { 37 | m.lock.Lock() 38 | defer m.lock.Unlock() 39 | 40 | if a, ok := m.Map[key]; ok { 41 | 42 | //握手连接存在 43 | if a.conn != nil { 44 | a.conn.Close() 45 | } 46 | } 47 | delete(m.Map, key) 48 | } 49 | 50 | //DelAll 51 | func (m *suMap) DelAll() { 52 | m.lock.Lock() 53 | defer m.lock.Unlock() 54 | 55 | //遍历Map 断开所有socks5握手连接 56 | for k, v := range m.Map { 57 | v.conn.Close() 58 | delete(m.Map, k) 59 | 60 | } 61 | } 62 | 63 | // Get ... 64 | func (m *suMap) Get(key int64) (a su, b bool) { 65 | m.lock.RLock() 66 | defer m.lock.RUnlock() 67 | a, b = m.Map[key] 68 | return 69 | } 70 | 71 | /* 72 | func main() { 73 | 74 | as := NewSuMap() 75 | 76 | for i := 0; i < 500; i++ { 77 | 78 | conn, err := net.DialTimeout("tcp", "47.102.149.3:1080", time.Second*2) 79 | if err != nil { 80 | fmt.Println(err) 81 | return 82 | } 83 | addr, err := net.ResolveUDPAddr("udp", "47.102.149.3:1080") 84 | if err != nil { 85 | fmt.Println(err) 86 | return 87 | } 88 | 89 | as.Set(int64(i), conn, addr) 90 | 91 | go func(abc int64) { 92 | time.Sleep(20 * time.Second) 93 | defer as.Del(abc) 94 | fmt.Println("del", abc) 95 | }(int64(i)) 96 | 97 | fmt.Println(int64(i)) 98 | 99 | } 100 | 101 | select {} 102 | } 103 | */ 104 | -------------------------------------------------------------------------------- /Sokcs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "strconv" 7 | "time" 8 | 9 | "github.com/FlowerWrong/gosocks" 10 | ) 11 | 12 | func SocksUDPHandshake(ip string, port int, user, pass string) (net.Addr, net.Conn, error) { 13 | 14 | b := gosocks.SocksDialer{ 15 | Timeout: time.Second * 5, 16 | Auth: &gosocks.AnonymousClientAuthenticator{}, 17 | ControlFun: nil, 18 | } 19 | 20 | rDr := "postgres://" + user + ":" + pass + "@" + ip + ":" + strconv.Itoa(port) 21 | 22 | socks5TcpConn, err := b.Dial(rDr) 23 | if err != nil { 24 | return nil, nil, err 25 | } 26 | 27 | _, err = gosocks.WriteSocksRequest(socks5TcpConn, &gosocks.SocksRequest{ 28 | Cmd: gosocks.SocksCmdUDPAssociate, 29 | HostType: gosocks.SocksIPv4Host, 30 | DstHost: "0.0.0.0", 31 | DstPort: 0, 32 | }) 33 | cmdUDPAssociateReply, err := gosocks.ReadSocksReply(socks5TcpConn) 34 | if err != nil { 35 | socks5TcpConn.Close() 36 | return nil, nil, err 37 | } 38 | 39 | if cmdUDPAssociateReply.Rep != gosocks.SocksSucceeded { 40 | socks5TcpConn.Close() 41 | return nil, nil, fmt.Errorf("hand err") 42 | } 43 | 44 | return gosocks.SocksAddrToNetAddr("udp", ip, cmdUDPAssociateReply.BndPort), socks5TcpConn, nil 45 | } 46 | -------------------------------------------------------------------------------- /TcpMap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | /* 8 | 此Map用于储存 一条链接的最终目的地址 和发起请求的进程ID 9 | 10 | key为本地端口 11 | */ 12 | 13 | // TcpMap 14 | type TcpMap struct { 15 | Map map[int]TcpMapInfo 16 | lock *sync.RWMutex // 加锁 17 | } 18 | 19 | type TcpMapInfo struct { 20 | pid uint64 //进程id 21 | ip []byte //连接的目标地址 22 | } 23 | 24 | func NewTcpMap() *TcpMap { 25 | return &TcpMap{Map: make(map[int]TcpMapInfo), lock: new(sync.RWMutex)} 26 | } 27 | 28 | // Set ... 29 | func (m *TcpMap) Set(key int, pid uint64, ip []byte) { 30 | m.lock.Lock() 31 | defer m.lock.Unlock() 32 | m.Map[key] = TcpMapInfo{pid: pid, ip: ip} 33 | } 34 | 35 | //Del 36 | func (m *TcpMap) Del(key int) { 37 | m.lock.Lock() 38 | defer m.lock.Unlock() 39 | delete(m.Map, key) 40 | } 41 | 42 | // Get ... 43 | func (m *TcpMap) Get(key int) (a TcpMapInfo, b bool) { 44 | m.lock.RLock() 45 | defer m.lock.RUnlock() 46 | a, b = m.Map[key] 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /core/cipher.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "crypto/md5" 5 | "errors" 6 | "net" 7 | "sort" 8 | "strings" 9 | 10 | "NewProxy/shadowaead" 11 | "NewProxy/shadowstream" 12 | ) 13 | 14 | type Cipher interface { 15 | StreamConnCipher 16 | PacketConnCipher 17 | } 18 | 19 | type StreamConnCipher interface { 20 | StreamConn(net.Conn) net.Conn 21 | } 22 | 23 | type PacketConnCipher interface { 24 | PacketConn(net.PacketConn) net.PacketConn 25 | } 26 | 27 | // ErrCipherNotSupported occurs when a cipher is not supported (likely because of security concerns). 28 | var ErrCipherNotSupported = errors.New("cipher not supported") 29 | 30 | const ( 31 | aeadAes128Gcm = "AEAD_AES_128_GCM" 32 | aeadAes192Gcm = "AEAD_AES_192_GCM" 33 | aeadAes256Gcm = "AEAD_AES_256_GCM" 34 | aeadChacha20Poly1305 = "AEAD_CHACHA20_POLY1305" 35 | ) 36 | 37 | // List of AEAD ciphers: key size in bytes and constructor 38 | var aeadList = map[string]struct { 39 | KeySize int 40 | New func([]byte) (shadowaead.Cipher, error) 41 | }{ 42 | aeadAes128Gcm: {16, shadowaead.AESGCM}, 43 | aeadAes192Gcm: {24, shadowaead.AESGCM}, 44 | aeadAes256Gcm: {32, shadowaead.AESGCM}, 45 | aeadChacha20Poly1305: {32, shadowaead.Chacha20Poly1305}, 46 | } 47 | 48 | // List of stream ciphers: key size in bytes and constructor 49 | var streamList = map[string]struct { 50 | KeySize int 51 | New func(key []byte) (shadowstream.Cipher, error) 52 | }{ 53 | "AES-128-CTR": {16, shadowstream.AESCTR}, 54 | "AES-192-CTR": {24, shadowstream.AESCTR}, 55 | "AES-256-CTR": {32, shadowstream.AESCTR}, 56 | "AES-128-CFB": {16, shadowstream.AESCFB}, 57 | "AES-192-CFB": {24, shadowstream.AESCFB}, 58 | "AES-256-CFB": {32, shadowstream.AESCFB}, 59 | "CHACHA20-IETF": {32, shadowstream.Chacha20IETF}, 60 | "XCHACHA20": {32, shadowstream.Xchacha20}, 61 | } 62 | 63 | // ListCipher returns a list of available cipher names sorted alphabetically. 64 | func ListCipher() []string { 65 | var l []string 66 | for k := range aeadList { 67 | l = append(l, k) 68 | } 69 | for k := range streamList { 70 | l = append(l, k) 71 | } 72 | sort.Strings(l) 73 | return l 74 | } 75 | 76 | // PickCipher returns a Cipher of the given name. Derive key from password if given key is empty. 77 | func PickCipher(name string, key []byte, password string) (Cipher, error) { 78 | name = strings.ToUpper(name) 79 | 80 | switch name { 81 | case "DUMMY": 82 | return &dummy{}, nil 83 | case "CHACHA20-IETF-POLY1305": 84 | name = aeadChacha20Poly1305 85 | case "AES-128-GCM": 86 | name = aeadAes128Gcm 87 | case "AES-192-GCM": 88 | name = aeadAes192Gcm 89 | case "AES-256-GCM": 90 | name = aeadAes256Gcm 91 | } 92 | 93 | if choice, ok := aeadList[name]; ok { 94 | if len(key) == 0 { 95 | key = kdf(password, choice.KeySize) 96 | } 97 | if len(key) != choice.KeySize { 98 | return nil, shadowaead.KeySizeError(choice.KeySize) 99 | } 100 | aead, err := choice.New(key) 101 | return &aeadCipher{aead}, err 102 | } 103 | 104 | if choice, ok := streamList[name]; ok { 105 | if len(key) == 0 { 106 | key = kdf(password, choice.KeySize) 107 | } 108 | if len(key) != choice.KeySize { 109 | return nil, shadowstream.KeySizeError(choice.KeySize) 110 | } 111 | ciph, err := choice.New(key) 112 | return &streamCipher{ciph}, err 113 | } 114 | 115 | return nil, ErrCipherNotSupported 116 | } 117 | 118 | type aeadCipher struct{ shadowaead.Cipher } 119 | 120 | func (aead *aeadCipher) StreamConn(c net.Conn) net.Conn { return shadowaead.NewConn(c, aead) } 121 | func (aead *aeadCipher) PacketConn(c net.PacketConn) net.PacketConn { 122 | return shadowaead.NewPacketConn(c, aead) 123 | } 124 | 125 | type streamCipher struct{ shadowstream.Cipher } 126 | 127 | func (ciph *streamCipher) StreamConn(c net.Conn) net.Conn { return shadowstream.NewConn(c, ciph) } 128 | func (ciph *streamCipher) PacketConn(c net.PacketConn) net.PacketConn { 129 | return shadowstream.NewPacketConn(c, ciph) 130 | } 131 | 132 | // dummy cipher does not encrypt 133 | 134 | type dummy struct{} 135 | 136 | func (dummy) StreamConn(c net.Conn) net.Conn { return c } 137 | func (dummy) PacketConn(c net.PacketConn) net.PacketConn { return c } 138 | 139 | // key-derivation function from original Shadowsocks 140 | func kdf(password string, keyLen int) []byte { 141 | var b, prev []byte 142 | h := md5.New() 143 | for len(b) < keyLen { 144 | h.Write(prev) 145 | h.Write([]byte(password)) 146 | b = h.Sum(b) 147 | prev = b[len(b)-h.Size():] 148 | h.Reset() 149 | } 150 | return b[:keyLen] 151 | } 152 | -------------------------------------------------------------------------------- /core/doc.go: -------------------------------------------------------------------------------- 1 | // Package core implements essential parts of Shadowsocks 2 | package core 3 | -------------------------------------------------------------------------------- /core/packet.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "net" 4 | 5 | func ListenPacket(network, address string, ciph PacketConnCipher) (net.PacketConn, error) { 6 | c, err := net.ListenPacket(network, address) 7 | return ciph.PacketConn(c), err 8 | } 9 | -------------------------------------------------------------------------------- /core/stream.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "net" 4 | 5 | type listener struct { 6 | net.Listener 7 | StreamConnCipher 8 | } 9 | 10 | func Listen(network, address string, ciph StreamConnCipher) (net.Listener, error) { 11 | l, err := net.Listen(network, address) 12 | return &listener{l, ciph}, err 13 | } 14 | 15 | func (l *listener) Accept() (net.Conn, error) { 16 | c, err := l.Listener.Accept() 17 | return l.StreamConn(c), err 18 | } 19 | 20 | func Dial(network, address string, ciph StreamConnCipher) (net.Conn, error) { 21 | c, err := net.Dial(network, address) 22 | return ciph.StreamConn(c), err 23 | } 24 | -------------------------------------------------------------------------------- /dns.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo LDFLAGS: -lwsock32 5 | #cgo LDFLAGS: -lWs2_32 6 | #cgo CFLAGS: -I ./include 7 | #cgo LDFLAGS: -L ./lib -lnfapi 8 | 9 | #include 10 | #include 11 | #include "nfapi.h" 12 | #include "Driver.h" 13 | */ 14 | import "C" 15 | 16 | import ( 17 | "fmt" 18 | "net" 19 | "time" 20 | "unsafe" 21 | ) 22 | 23 | func DNSRequest(id C.ENDPOINT_ID, remoteAddress *C.uchar, buf []byte, options C.PNF_UDP_OPTIONS) { 24 | 25 | conn, err := net.ListenPacket("udp", "") 26 | if err != nil { 27 | return 28 | } 29 | defer conn.Close() 30 | 31 | if DnsPAddr != nil { 32 | conn = DnsPacket.PacketConn(conn) 33 | //给数据加包头 34 | 35 | hostType, host, port, err := NetAddrToSocksAddr(DnsAddr) 36 | if err != nil { 37 | return 38 | } 39 | 40 | var buff = []byte{hostType} 41 | buff = append(buff, host[:]...) 42 | buff = append(buff, port[:]...) 43 | buff = append(buff, buf[:]...) 44 | 45 | _, err = conn.WriteTo(buff[:], DnsPAddr) 46 | if err != nil { 47 | return 48 | } 49 | 50 | } else { 51 | _, err = conn.WriteTo(buf[:], DnsAddr) 52 | if err != nil { 53 | return 54 | } 55 | } 56 | 57 | rbuf := make([]byte, 1024) 58 | conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(DnsOut))) 59 | n, _, err := conn.ReadFrom(rbuf) 60 | if err != nil { 61 | return 62 | } 63 | 64 | //ss 去掉协议头 65 | if DnsPAddr != nil { 66 | 67 | var ssbuf []byte 68 | if rbuf[0] == AtypIPv4 { 69 | ssbuf = rbuf[7:n] 70 | } else { 71 | ssbuf = rbuf[19:n] 72 | } 73 | 74 | C.nf_udpPostReceive(id, remoteAddress, (*C.char)(unsafe.Pointer(&ssbuf[0])), C.int(len(ssbuf)), options) 75 | return 76 | } 77 | 78 | C.nf_udpPostReceive(id, remoteAddress, (*C.char)(unsafe.Pointer(&rbuf[0])), C.int(n), options) 79 | } 80 | 81 | func NetAddrToSocksAddr(addr interface{}) (hostType byte, host []byte, port [2]byte, err error) { 82 | 83 | switch addr.(type) { 84 | case *net.UDPAddr: 85 | a := addr.(*net.UDPAddr) 86 | hostType = AtypIPv4 87 | host = a.IP.To4() 88 | port = Htons(uint16(a.Port)) 89 | case *net.TCPAddr: 90 | a := addr.(*net.TCPAddr) 91 | hostType = AtypIPv4 92 | host = a.IP.To4() 93 | port = Htons(uint16(a.Port)) 94 | default: 95 | err = fmt.Errorf("err") 96 | } 97 | 98 | return 99 | } 100 | -------------------------------------------------------------------------------- /include/nfapi.h: -------------------------------------------------------------------------------- 1 | // 2 | // NetFilterSDK 3 | // Copyright (C) 2009 Vitaly Sidorov 4 | // All rights reserved. 5 | // 6 | // This file is a part of the NetFilter SDK. 7 | // The code and information is provided "as-is" without 8 | // warranty of any kind, either expressed or implied. 9 | // 10 | 11 | #define _C_API 12 | 13 | #ifndef _NFAPI_H 14 | #define _NFAPI_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | //#include 21 | #include "nfevents.h" 22 | 23 | #ifdef _NFAPI_STATIC_LIB 24 | #define NFAPI_API 25 | #else 26 | #ifdef NFAPI_EXPORTS 27 | #define NFAPI_API __declspec(dllexport) 28 | #else 29 | #define NFAPI_API __declspec(dllimport) 30 | #endif 31 | #endif 32 | 33 | // Flags for NF_UDP_OPTIONS.flags 34 | 35 | #define TDI_RECEIVE_BROADCAST 0x00000004 // received TSDU was broadcast. 36 | #define TDI_RECEIVE_MULTICAST 0x00000008 // received TSDU was multicast. 37 | #define TDI_RECEIVE_PARTIAL 0x00000010 // received TSDU is not fully presented. 38 | #define TDI_RECEIVE_NORMAL 0x00000020 // received TSDU is normal data 39 | #define TDI_RECEIVE_EXPEDITED 0x00000040 // received TSDU is expedited data 40 | #define TDI_RECEIVE_PEEK 0x00000080 // received TSDU is not released 41 | #define TDI_RECEIVE_NO_RESPONSE_EXP 0x00000100 // HINT: no back-traffic expected 42 | #define TDI_RECEIVE_COPY_LOOKAHEAD 0x00000200 // for kernel-mode indications 43 | #define TDI_RECEIVE_ENTIRE_MESSAGE 0x00000400 // opposite of RECEIVE_PARTIAL 44 | // (for kernel-mode indications) 45 | #define TDI_RECEIVE_AT_DISPATCH_LEVEL 0x00000800 // receive indication called 46 | // at dispatch level 47 | #define TDI_RECEIVE_CONTROL_INFO 0x00001000 // Control info is being passed up. 48 | #define TDI_RECEIVE_FORCE_INDICATION 0x00002000 // reindicate rejected data. 49 | #define TDI_RECEIVE_NO_PUSH 0x00004000 // complete only when full. 50 | 51 | typedef enum _NF_FLAGS 52 | { 53 | NFF_NONE = 0, 54 | NFF_DONT_DISABLE_TEREDO = 1, 55 | NFF_DONT_DISABLE_TCP_OFFLOADING = 2, 56 | NFF_DONT_ADD_ANTIVIRUS_EXCEPTIONS = 4 57 | } NF_FLAGS; 58 | 59 | #ifndef _C_API 60 | namespace nfapi 61 | { 62 | #define NFAPI_NS nfapi:: 63 | #define NFAPI_CC 64 | #else // _C_API 65 | #define NFAPI_CC __cdecl 66 | #define NFAPI_NS 67 | #ifdef __cplusplus 68 | extern "C" 69 | { 70 | #endif 71 | #endif // _C_API 72 | 73 | /** 74 | * Initializes the internal data structures and starts the filtering thread. 75 | * @param driverName The name of hooking driver, without ".sys" extension. 76 | * @param pHandler Pointer to event handling object 77 | **/ 78 | NFAPI_API NF_STATUS NFAPI_CC nf_init(const char * driverName, NF_EventHandler * pHandler); 79 | 80 | /** 81 | * Stops the filtering thread, breaks all filtered connections and closes 82 | * a connection with the hooking driver. 83 | **/ 84 | NFAPI_API void NFAPI_CC 85 | nf_free(); 86 | 87 | /** 88 | * Registers and starts a driver with specified name (without ".sys" extension) 89 | * @param driverName 90 | **/ 91 | NFAPI_API NF_STATUS NFAPI_CC 92 | nf_registerDriver(const char * driverName); 93 | 94 | /** 95 | * Unregisters a driver with specified name (without ".sys" extension) 96 | * @param driverName 97 | **/ 98 | NFAPI_API NF_STATUS NFAPI_CC 99 | nf_unRegisterDriver(const char * driverName); 100 | 101 | 102 | // 103 | // TCP control routines 104 | // 105 | 106 | /** 107 | * Suspends or resumes indicating of sends and receives for specified connection. 108 | * @param id Connection identifier 109 | * @param suspended TRUE(1) for suspend, FALSE(0) for resume 110 | **/ 111 | NFAPI_API NF_STATUS NFAPI_CC 112 | nf_tcpSetConnectionState(ENDPOINT_ID id, int suspended); 113 | 114 | /** 115 | * Sends the buffer to remote server via specified connection. 116 | * @param id Connection identifier 117 | * @param buf Pointer to data buffer 118 | * @param len Buffer length 119 | **/ 120 | NFAPI_API NF_STATUS NFAPI_CC 121 | nf_tcpPostSend(ENDPOINT_ID id, const char * buf, int len); 122 | 123 | /** 124 | * Indicates the buffer to local process via specified connection. 125 | * @param id Unique connection identifier 126 | * @param buf Pointer to data buffer 127 | * @param len Buffer length 128 | **/ 129 | NFAPI_API NF_STATUS NFAPI_CC 130 | nf_tcpPostReceive(ENDPOINT_ID id, const char * buf, int len); 131 | 132 | /** 133 | * Breaks the connection with given id. 134 | * @param id Connection identifier 135 | **/ 136 | NFAPI_API NF_STATUS NFAPI_CC 137 | nf_tcpClose(ENDPOINT_ID id); 138 | 139 | /** 140 | * Sets the timeout for TCP connections and returns old timeout. 141 | * @param timeout Timeout value in milliseconds. Specify zero value to disable timeouts. 142 | */ 143 | NFAPI_API unsigned long NFAPI_CC 144 | nf_setTCPTimeout(unsigned long timeout); 145 | 146 | /** 147 | * Disables indicating TCP packets to user mode for the specified endpoint 148 | * @param id Socket identifier 149 | */ 150 | NFAPI_API NF_STATUS NFAPI_CC 151 | nf_tcpDisableFiltering(ENDPOINT_ID id); 152 | 153 | 154 | // 155 | // UDP control routines 156 | // 157 | 158 | /** 159 | * Suspends or resumes indicating of sends and receives for specified socket. 160 | * @param id Socket identifier 161 | * @param suspended TRUE(1) for suspend, FALSE(0) for resume 162 | **/ 163 | NFAPI_API NF_STATUS NFAPI_CC 164 | nf_udpSetConnectionState(ENDPOINT_ID id, int suspended); 165 | 166 | /** 167 | * Sends the buffer to remote server via specified socket. 168 | * @param id Socket identifier 169 | * @param options UDP options 170 | * @param remoteAddress Destination address 171 | * @param buf Pointer to data buffer 172 | * @param len Buffer length 173 | **/ 174 | NFAPI_API NF_STATUS NFAPI_CC 175 | nf_udpPostSend(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 176 | 177 | /** 178 | * Indicates the buffer to local process via specified socket. 179 | * @param id Unique connection identifier 180 | * @param options UDP options 181 | * @param remoteAddress Source address 182 | * @param buf Pointer to data buffer 183 | * @param len Buffer length 184 | **/ 185 | NFAPI_API NF_STATUS NFAPI_CC 186 | nf_udpPostReceive(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 187 | 188 | /** 189 | * Disables indicating UDP packets to user mode for the specified endpoint 190 | * @param id Socket identifier 191 | */ 192 | NFAPI_API NF_STATUS NFAPI_CC 193 | nf_udpDisableFiltering(ENDPOINT_ID id); 194 | 195 | 196 | /** 197 | * Sends a packet to remote IP 198 | * @param buf Pointer to IP packet 199 | * @param len Buffer length 200 | * @param options IP options 201 | **/ 202 | NFAPI_API NF_STATUS NFAPI_CC 203 | nf_ipPostSend(const char * buf, int len, PNF_IP_PACKET_OPTIONS options); 204 | 205 | /** 206 | * Indicates a packet to TCP/IP stack 207 | * @param buf Pointer to IP packet 208 | * @param len Buffer length 209 | * @param options IP options 210 | **/ 211 | NFAPI_API NF_STATUS NFAPI_CC 212 | nf_ipPostReceive(const char * buf, int len, PNF_IP_PACKET_OPTIONS options); 213 | 214 | // 215 | // Filtering rules 216 | // 217 | 218 | /** 219 | * Add a rule to the head of rules list in driver. 220 | * @param pRule See NF_RULE 221 | * @param toHead TRUE (1) - add rule to list head, FALSE (0) - add rule to tail 222 | **/ 223 | NFAPI_API NF_STATUS NFAPI_CC 224 | nf_addRule(PNF_RULE pRule, int toHead); 225 | 226 | /** 227 | * Removes all rules from driver. 228 | **/ 229 | NFAPI_API NF_STATUS NFAPI_CC 230 | nf_deleteRules(); 231 | 232 | /** 233 | * Replace the rules in driver with the specified array. 234 | * @param pRules Array of NF_RULE structures 235 | * @param count Number of items in array 236 | **/ 237 | NFAPI_API NF_STATUS NFAPI_CC 238 | nf_setRules(PNF_RULE pRules, int count); 239 | 240 | /** 241 | * Add a rule to the head of rules list in driver. 242 | * @param pRule See NF_RULE_EX 243 | * @param toHead TRUE (1) - add rule to list head, FALSE (0) - add rule to tail 244 | **/ 245 | NFAPI_API NF_STATUS NFAPI_CC 246 | nf_addRuleEx(PNF_RULE_EX pRule, int toHead); 247 | 248 | /** 249 | * Replace the rules in driver with the specified array. 250 | * @param pRules Array of NF_RULE_EX structures 251 | * @param count Number of items in array 252 | **/ 253 | NFAPI_API NF_STATUS NFAPI_CC 254 | nf_setRulesEx(PNF_RULE_EX pRules, int count); 255 | 256 | // 257 | // Debug routine 258 | // 259 | 260 | NFAPI_API unsigned long NFAPI_CC 261 | nf_getConnCount(); 262 | 263 | NFAPI_API NF_STATUS NFAPI_CC 264 | nf_tcpSetSockOpt(ENDPOINT_ID id, int optname, const char* optval, int optlen); 265 | 266 | /** 267 | * Returns the process name for given process id 268 | * @param processId Process identifier 269 | * @param buf Buffer 270 | * @param len Buffer length 271 | **/ 272 | NFAPI_API BOOL NFAPI_CC 273 | nf_getProcessNameA(DWORD processId, char * buf, DWORD len); 274 | 275 | NFAPI_API BOOL NFAPI_CC 276 | nf_getProcessNameW(DWORD processId, wchar_t * buf, DWORD len); 277 | 278 | #ifdef UNICODE 279 | #define nf_getProcessName nf_getProcessNameW 280 | #else 281 | #define nf_getProcessName nf_getProcessNameA 282 | #endif 283 | 284 | NFAPI_API BOOL NFAPI_CC 285 | nf_getProcessNameFromKernel(DWORD processId, wchar_t * buf, DWORD len); 286 | 287 | /** 288 | * Allows the current process to see the names of all processes in system 289 | **/ 290 | NFAPI_API void NFAPI_CC 291 | nf_adjustProcessPriviledges(); 292 | 293 | /** 294 | * Returns TRUE if the specified process acts as a local proxy, accepting the redirected TCP connections. 295 | **/ 296 | NFAPI_API BOOL NFAPI_CC 297 | nf_tcpIsProxy(DWORD processId); 298 | 299 | /** 300 | * Set the number of worker threads and initialization flags. 301 | * The function should be called before nf_init. 302 | * By default nThreads = 1 and flags = 0 303 | * @param nThreads Number of worker threads for NF_EventHandler events 304 | * @param flags A combination of flags from NF_FLAGS 305 | **/ 306 | NFAPI_API void NFAPI_CC 307 | nf_setOptions(DWORD nThreads, DWORD flags); 308 | 309 | /** 310 | * Complete TCP connect request pended using flag NF_PEND_CONNECT_REQUEST. 311 | **/ 312 | NFAPI_API NF_STATUS NFAPI_CC 313 | nf_completeTCPConnectRequest(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 314 | 315 | /** 316 | * Complete UDP connect request pended using flag NF_PEND_CONNECT_REQUEST. 317 | **/ 318 | NFAPI_API NF_STATUS NFAPI_CC 319 | nf_completeUDPConnectRequest(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnInfo); 320 | 321 | /** 322 | * Returns in pConnInfo the properties of TCP connection with specified id. 323 | **/ 324 | NFAPI_API NF_STATUS NFAPI_CC 325 | nf_getTCPConnInfo(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 326 | 327 | /** 328 | * Returns in pConnInfo the properties of UDP socket with specified id. 329 | **/ 330 | NFAPI_API NF_STATUS NFAPI_CC 331 | nf_getUDPConnInfo(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 332 | 333 | /** 334 | * Set the event handler for IP filtering events 335 | */ 336 | NFAPI_API void NFAPI_CC 337 | nf_setIPEventHandler(NF_IPEventHandler * pHandler); 338 | 339 | /** 340 | * Add flow control context 341 | */ 342 | NFAPI_API NF_STATUS NFAPI_CC 343 | nf_addFlowCtl(PNF_FLOWCTL_DATA pData, unsigned int * pFcHandle); 344 | 345 | /** 346 | * Delete flow control context 347 | */ 348 | NFAPI_API NF_STATUS NFAPI_CC 349 | nf_deleteFlowCtl(unsigned int fcHandle); 350 | 351 | /** 352 | * Associate flow control context with TCP connection 353 | */ 354 | NFAPI_API NF_STATUS NFAPI_CC 355 | nf_setTCPFlowCtl(ENDPOINT_ID id, unsigned int fcHandle); 356 | 357 | /** 358 | * Associate flow control context with UDP socket 359 | */ 360 | NFAPI_API NF_STATUS NFAPI_CC 361 | nf_setUDPFlowCtl(ENDPOINT_ID id, unsigned int fcHandle); 362 | 363 | /** 364 | * Modify flow control context limits 365 | */ 366 | NFAPI_API NF_STATUS NFAPI_CC 367 | nf_modifyFlowCtl(unsigned int fcHandle, PNF_FLOWCTL_DATA pData); 368 | 369 | /** 370 | * Get flow control context statistics as the numbers of in/out bytes 371 | */ 372 | NFAPI_API NF_STATUS NFAPI_CC 373 | nf_getFlowCtlStat(unsigned int fcHandle, PNF_FLOWCTL_STAT pStat); 374 | 375 | /** 376 | * Get TCP connection statistics as the numbers of in/out bytes. 377 | * The function can be called only from tcpClosed handler! 378 | */ 379 | NFAPI_API NF_STATUS NFAPI_CC 380 | nf_getTCPStat(ENDPOINT_ID id, PNF_FLOWCTL_STAT pStat); 381 | 382 | /** 383 | * Get UDP socket statistics as the numbers of in/out bytes. 384 | * The function can be called only from udpClosed handler! 385 | */ 386 | NFAPI_API NF_STATUS NFAPI_CC 387 | nf_getUDPStat(ENDPOINT_ID id, PNF_FLOWCTL_STAT pStat); 388 | 389 | /** 390 | * Add binding rule to driver 391 | */ 392 | NFAPI_API NF_STATUS NFAPI_CC 393 | nf_addBindingRule(PNF_BINDING_RULE pRule, int toHead); 394 | 395 | /** 396 | * Delete all binding rules from driver 397 | */ 398 | NFAPI_API NF_STATUS NFAPI_CC 399 | nf_deleteBindingRules(); 400 | 401 | /** 402 | * Returns the type of attached driver (DT_WFP, DT_TDI or DT_UNKNOWN) 403 | */ 404 | NFAPI_API unsigned long NFAPI_CC 405 | nf_getDriverType(); 406 | 407 | #ifdef __cplusplus 408 | } 409 | #endif 410 | 411 | #endif -------------------------------------------------------------------------------- /include/nfdriver.h: -------------------------------------------------------------------------------- 1 | // 2 | // NetFilterSDK 3 | // Copyright (C) 2013 Vitaly Sidorov 4 | // All rights reserved. 5 | // 6 | // This file is a part of the NetFilter SDK. 7 | // The code and information is provided "as-is" without 8 | // warranty of any kind, either expressed or implied. 9 | // 10 | 11 | 12 | #ifndef _NFDRIVER_H 13 | #define _NFDRIVER_H 14 | 15 | #define NF_TCP_PACKET_BUF_SIZE 8192 16 | #define NF_UDP_PACKET_BUF_SIZE 2 * 65536 17 | 18 | /** 19 | * IO data codes 20 | **/ 21 | typedef enum _NF_DATA_CODE 22 | { 23 | NF_TCP_CONNECTED, // TCP connection established 24 | NF_TCP_CLOSED, // TCP connection closed 25 | NF_TCP_RECEIVE, // TCP data packet received 26 | NF_TCP_SEND, // TCP data packet sent 27 | NF_TCP_CAN_RECEIVE, // The buffer for TCP receives is empty 28 | NF_TCP_CAN_SEND, // The buffer for TCP sends is empty 29 | NF_TCP_REQ_SUSPEND, // Requests suspending TCP connection 30 | NF_TCP_REQ_RESUME, // Requests resuming TCP connection 31 | 32 | NF_UDP_CREATED, // UDP socket created 33 | NF_UDP_CLOSED, // UDP socket closed 34 | NF_UDP_RECEIVE, // UDP data packet received 35 | NF_UDP_SEND, // UDP data packet sent 36 | NF_UDP_CAN_RECEIVE, // The buffer for UDP receives is empty 37 | NF_UDP_CAN_SEND, // The buffer for UDP sends is empty 38 | NF_UDP_REQ_SUSPEND, // Requests suspending UDP address 39 | NF_UDP_REQ_RESUME, // Requests resuming UDP address 40 | 41 | NF_REQ_ADD_HEAD_RULE, // Add a rule to list head 42 | NF_REQ_ADD_TAIL_RULE, // Add a rule to list tail 43 | NF_REQ_DELETE_RULES, // Remove all rules 44 | 45 | NF_TCP_CONNECT_REQUEST, // Outgoing TCP connect request 46 | NF_UDP_CONNECT_REQUEST, // Outgoing UDP connect request 47 | 48 | NF_TCP_DISABLE_USER_MODE_FILTERING, // Disable indicating TCP packets to user mode for a connection 49 | NF_UDP_DISABLE_USER_MODE_FILTERING, // Disable indicating UDP packets to user mode for a socket 50 | 51 | NF_REQ_SET_TCP_OPT, // Set TCP socket options 52 | NF_REQ_IS_PROXY, // Check if process with specified id is local proxy 53 | 54 | NF_TCP_REINJECT, // Reinject pended packets 55 | NF_TCP_REMOVE_CLOSED, // Delete TCP context for the closed connection 56 | NF_TCP_DEFERRED_DISCONNECT, // Delete TCP context for the closed connection 57 | 58 | NF_IP_RECEIVE, // IP data packet received 59 | NF_IP_SEND, // IP data packet sent 60 | NF_TCP_RECEIVE_PUSH, // Push all TCP data packets 61 | } NF_DATA_CODE; 62 | 63 | typedef enum _NF_DIRECTION 64 | { 65 | NF_D_IN = 1, // Incoming TCP connection or UDP packet 66 | NF_D_OUT = 2, // Outgoing TCP connection or UDP packet 67 | NF_D_BOTH = 3 // Any direction 68 | } NF_DIRECTION; 69 | 70 | typedef enum _NF_FILTERING_FLAG 71 | { 72 | NF_ALLOW = 0, // Allow the activity without filtering transmitted packets 73 | NF_BLOCK = 1, // Block the activity 74 | NF_FILTER = 2, // Filter the transmitted packets 75 | NF_SUSPENDED = 4, // Suspend receives from server and sends from client 76 | NF_OFFLINE = 8, // Emulate establishing a TCP connection with remote server 77 | NF_INDICATE_CONNECT_REQUESTS = 16, // Indicate outgoing connect requests to API 78 | NF_DISABLE_REDIRECT_PROTECTION = 32, // Disable blocking indicating connect requests for outgoing connections of local proxies 79 | NF_PEND_CONNECT_REQUEST = 64, // Pend outgoing connect request to complete it later using nf_complete(TCP|UDP)ConnectRequest 80 | NF_FILTER_AS_IP_PACKETS = 128, // Indicate the traffic as IP packets via ipSend/ipReceive 81 | NF_READONLY = 256, // Don't block the IP packets and indicate them to ipSend/ipReceive only for monitoring 82 | NF_CONTROL_FLOW = 512, // Use the flow limit rules even without NF_FILTER flag 83 | } NF_FILTERING_FLAG; 84 | 85 | #pragma pack(push, 1) 86 | 87 | #define NF_MAX_ADDRESS_LENGTH 28 88 | #define NF_MAX_IP_ADDRESS_LENGTH 16 89 | 90 | #ifndef AF_INET 91 | #define AF_INET 2 /* internetwork: UDP, TCP, etc. */ 92 | #endif 93 | 94 | #ifndef AF_INET6 95 | #define AF_INET6 23 /* Internetwork Version 6 */ 96 | #endif 97 | 98 | // Protocols 99 | 100 | #ifndef IPPROTO_TCP 101 | #define IPPROTO_TCP 6 102 | #endif 103 | 104 | #ifndef IPPROTO_UDP 105 | #define IPPROTO_UDP 17 106 | #endif 107 | 108 | #define TCP_SOCKET_NODELAY 1 109 | #define TCP_SOCKET_KEEPALIVE 2 110 | #define TCP_SOCKET_OOBINLINE 3 111 | #define TCP_SOCKET_BSDURGENT 4 112 | #define TCP_SOCKET_ATMARK 5 113 | #define TCP_SOCKET_WINDOW 6 114 | 115 | /** 116 | * Filtering rule 117 | **/ 118 | typedef UNALIGNED struct _NF_RULE 119 | { 120 | int protocol; // IPPROTO_TCP or IPPROTO_UDP 121 | unsigned long processId; // Process identifier 122 | unsigned char direction; // See NF_DIRECTION 123 | unsigned short localPort; // Local port 124 | unsigned short remotePort; // Remote port 125 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 126 | 127 | // Local IP (or network if localIpAddressMask is not zero) 128 | unsigned char localIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 129 | 130 | // Local IP mask 131 | unsigned char localIpAddressMask[NF_MAX_IP_ADDRESS_LENGTH]; 132 | 133 | // Remote IP (or network if remoteIpAddressMask is not zero) 134 | unsigned char remoteIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 135 | 136 | // Remote IP mask 137 | unsigned char remoteIpAddressMask[NF_MAX_IP_ADDRESS_LENGTH]; 138 | 139 | unsigned long filteringFlag; // See NF_FILTERING_FLAG 140 | } NF_RULE, *PNF_RULE; 141 | 142 | 143 | /** 144 | * Filtering rule with additional fields 145 | **/ 146 | typedef UNALIGNED struct _NF_RULE_EX 147 | { 148 | int protocol; // IPPROTO_TCP or IPPROTO_UDP 149 | unsigned long processId; // Process identifier 150 | unsigned char direction; // See NF_DIRECTION 151 | unsigned short localPort; // Local port 152 | unsigned short remotePort; // Remote port 153 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 154 | 155 | // Local IP (or network if localIpAddressMask is not zero) 156 | unsigned char localIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 157 | 158 | // Local IP mask 159 | unsigned char localIpAddressMask[NF_MAX_IP_ADDRESS_LENGTH]; 160 | 161 | // Remote IP (or network if remoteIpAddressMask is not zero) 162 | unsigned char remoteIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 163 | 164 | // Remote IP mask 165 | unsigned char remoteIpAddressMask[NF_MAX_IP_ADDRESS_LENGTH]; 166 | 167 | unsigned long filteringFlag; // See NF_FILTERING_FLAG 168 | 169 | // Process name tail mask (supports * as 0 or more symbols) 170 | wchar_t processName[MAX_PATH]; 171 | } NF_RULE_EX, *PNF_RULE_EX; 172 | 173 | typedef unsigned __int64 ENDPOINT_ID; 174 | 175 | 176 | /** 177 | * TCP connection properties 178 | **/ 179 | typedef UNALIGNED struct _NF_TCP_CONN_INFO 180 | { 181 | unsigned long filteringFlag; // See NF_FILTERING_FLAG 182 | unsigned long processId; // Process identifier 183 | unsigned char direction; // See NF_DIRECTION 184 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 185 | 186 | // Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6 187 | unsigned char localAddress[NF_MAX_ADDRESS_LENGTH]; 188 | 189 | // Remote address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6 190 | unsigned char remoteAddress[NF_MAX_ADDRESS_LENGTH]; 191 | 192 | } NF_TCP_CONN_INFO, *PNF_TCP_CONN_INFO; 193 | 194 | /** 195 | * UDP endpoint properties 196 | **/ 197 | typedef UNALIGNED struct _NF_UDP_CONN_INFO 198 | { 199 | unsigned long processId; // Process identifier 200 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 201 | 202 | // Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6 203 | unsigned char localAddress[NF_MAX_ADDRESS_LENGTH]; 204 | 205 | } NF_UDP_CONN_INFO, *PNF_UDP_CONN_INFO; 206 | 207 | /** 208 | * UDP TDI_CONNECT request properties 209 | **/ 210 | typedef UNALIGNED struct _NF_UDP_CONN_REQUEST 211 | { 212 | unsigned long filteringFlag; // See NF_FILTERING_FLAG 213 | unsigned long processId; // Process identifier 214 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 215 | 216 | // Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6 217 | unsigned char localAddress[NF_MAX_ADDRESS_LENGTH]; 218 | 219 | // Remote address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6 220 | unsigned char remoteAddress[NF_MAX_ADDRESS_LENGTH]; 221 | 222 | } NF_UDP_CONN_REQUEST, *PNF_UDP_CONN_REQUEST; 223 | 224 | /** 225 | * UDP options 226 | **/ 227 | typedef UNALIGNED struct _NF_UDP_OPTIONS 228 | { 229 | unsigned long flags; // Datagram flags 230 | long optionsLength; // Length of options buffer 231 | unsigned char options[1]; // Options of variable size 232 | } NF_UDP_OPTIONS, *PNF_UDP_OPTIONS; 233 | 234 | typedef enum _NF_IP_FLAG 235 | { 236 | NFIF_NONE = 0, // No flags 237 | NFIF_READONLY = 1, // The packet was not blocked and indicated only for monitoring in read-only mode 238 | // (see NF_READ_ONLY flags from NF_FILTERING_FLAG). 239 | } NF_IP_FLAG; 240 | 241 | /** 242 | * IP options 243 | **/ 244 | typedef struct _NF_IP_PACKET_OPTIONS 245 | { 246 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 247 | unsigned int ipHeaderSize; // Size in bytes of IP header 248 | unsigned long compartmentId; // Network routing compartment identifier (can be zero) 249 | unsigned long interfaceIndex; // Index of the interface on which the original packet data was received (irrelevant to outgoing packets) 250 | unsigned long subInterfaceIndex; // Index of the subinterface on which the original packet data was received (irrelevant to outgoing packets) 251 | unsigned long flags; // Can be a combination of flags from NF_IP_FLAG enumeration 252 | } NF_IP_PACKET_OPTIONS, *PNF_IP_PACKET_OPTIONS; 253 | 254 | /** 255 | * Internal IO structure 256 | **/ 257 | typedef UNALIGNED struct _NF_DATA 258 | { 259 | int code; 260 | ENDPOINT_ID id; 261 | unsigned long bufferSize; 262 | char buffer[1]; 263 | } NF_DATA, *PNF_DATA; 264 | 265 | typedef UNALIGNED struct _NF_BUFFERS 266 | { 267 | unsigned __int64 inBuf; 268 | unsigned __int64 inBufLen; 269 | unsigned __int64 outBuf; 270 | unsigned __int64 outBufLen; 271 | } NF_BUFFERS, *PNF_BUFFERS; 272 | 273 | typedef UNALIGNED struct _NF_READ_RESULT 274 | { 275 | unsigned __int64 length; 276 | } NF_READ_RESULT, *PNF_READ_RESULT; 277 | 278 | typedef UNALIGNED struct _NF_FLOWCTL_DATA 279 | { 280 | unsigned __int64 inLimit; 281 | unsigned __int64 outLimit; 282 | } NF_FLOWCTL_DATA, *PNF_FLOWCTL_DATA; 283 | 284 | typedef UNALIGNED struct _NF_FLOWCTL_MODIFY_DATA 285 | { 286 | unsigned int fcHandle; 287 | NF_FLOWCTL_DATA data; 288 | } NF_FLOWCTL_MODIFY_DATA, *PNF_FLOWCTL_MODIFY_DATA; 289 | 290 | typedef UNALIGNED struct _NF_FLOWCTL_STAT 291 | { 292 | unsigned __int64 inBytes; 293 | unsigned __int64 outBytes; 294 | } NF_FLOWCTL_STAT, *PNF_FLOWCTL_STAT; 295 | 296 | typedef UNALIGNED struct _NF_FLOWCTL_SET_DATA 297 | { 298 | unsigned __int64 endpointId; 299 | unsigned int fcHandle; 300 | } NF_FLOWCTL_SET_DATA, *PNF_FLOWCTL_SET_DATA; 301 | 302 | 303 | /** 304 | * Binding rule 305 | **/ 306 | typedef UNALIGNED struct _NF_BINDING_RULE 307 | { 308 | int protocol; // IPPROTO_TCP or IPPROTO_UDP 309 | 310 | unsigned long processId; // Process identifier 311 | 312 | // Process name tail mask (supports * as 0 or more symbols) 313 | wchar_t processName[MAX_PATH]; 314 | 315 | unsigned short localPort; // Local port 316 | 317 | unsigned short ip_family; // AF_INET for IPv4 and AF_INET6 for IPv6 318 | 319 | // Local IP (or network if localIpAddressMask is not zero) 320 | unsigned char localIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 321 | 322 | // Local IP mask 323 | unsigned char localIpAddressMask[NF_MAX_IP_ADDRESS_LENGTH]; 324 | 325 | // Redirect bind request to this IP 326 | unsigned char newLocalIpAddress[NF_MAX_IP_ADDRESS_LENGTH]; 327 | 328 | // Redirect bind request to this port, if it is not zero 329 | unsigned short newLocalPort; 330 | 331 | unsigned long filteringFlag; // See NF_FILTERING_FLAG, NF_ALLOW or NF_FILTER 332 | 333 | } NF_BINDING_RULE, *PNF_BINDING_RULE; 334 | 335 | 336 | #pragma pack(pop) 337 | 338 | typedef enum _NF_DRIVER_TYPE 339 | { 340 | DT_UNKNOWN = 0, 341 | DT_TDI = 1, 342 | DT_WFP = 2 343 | } NF_DRIVER_TYPE; 344 | 345 | #ifdef _NF_INTERNALS 346 | 347 | #define NF_REQ_GET_ADDR_INFO \ 348 | CTL_CODE(FILE_DEVICE_UNKNOWN, 101, METHOD_BUFFERED, FILE_ANY_ACCESS) 349 | 350 | #define NF_REQ_GET_PROCESS_NAME \ 351 | CTL_CODE(FILE_DEVICE_UNKNOWN, 102, METHOD_BUFFERED, FILE_ANY_ACCESS) 352 | 353 | #define NF_REQ_GET_DRIVER_TYPE \ 354 | CTL_CODE(FILE_DEVICE_UNKNOWN, 103, METHOD_BUFFERED, FILE_ANY_ACCESS) 355 | 356 | #define NF_REQ_TCP_ABORT \ 357 | CTL_CODE(FILE_DEVICE_UNKNOWN, 104, METHOD_BUFFERED, FILE_ANY_ACCESS) 358 | 359 | #define NF_REQ_ADD_FLOW_CTL \ 360 | CTL_CODE(FILE_DEVICE_UNKNOWN, 105, METHOD_BUFFERED, FILE_ANY_ACCESS) 361 | 362 | #define NF_REQ_DELETE_FLOW_CTL \ 363 | CTL_CODE(FILE_DEVICE_UNKNOWN, 106, METHOD_BUFFERED, FILE_ANY_ACCESS) 364 | 365 | #define NF_REQ_SET_TCP_FLOW_CTL \ 366 | CTL_CODE(FILE_DEVICE_UNKNOWN, 107, METHOD_BUFFERED, FILE_ANY_ACCESS) 367 | 368 | #define NF_REQ_SET_UDP_FLOW_CTL \ 369 | CTL_CODE(FILE_DEVICE_UNKNOWN, 108, METHOD_BUFFERED, FILE_ANY_ACCESS) 370 | 371 | #define NF_REQ_MODIFY_FLOW_CTL \ 372 | CTL_CODE(FILE_DEVICE_UNKNOWN, 109, METHOD_BUFFERED, FILE_ANY_ACCESS) 373 | 374 | #define NF_REQ_GET_FLOW_CTL_STAT \ 375 | CTL_CODE(FILE_DEVICE_UNKNOWN, 110, METHOD_BUFFERED, FILE_ANY_ACCESS) 376 | 377 | #define NF_REQ_CLEAR_TEMP_RULES \ 378 | CTL_CODE(FILE_DEVICE_UNKNOWN, 111, METHOD_BUFFERED, FILE_ANY_ACCESS) 379 | 380 | #define NF_REQ_ADD_TEMP_RULE \ 381 | CTL_CODE(FILE_DEVICE_UNKNOWN, 112, METHOD_BUFFERED, FILE_ANY_ACCESS) 382 | 383 | #define NF_REQ_SET_TEMP_RULES \ 384 | CTL_CODE(FILE_DEVICE_UNKNOWN, 113, METHOD_BUFFERED, FILE_ANY_ACCESS) 385 | 386 | #define NF_REQ_ADD_HEAD_BINDING_RULE \ 387 | CTL_CODE(FILE_DEVICE_UNKNOWN, 114, METHOD_BUFFERED, FILE_ANY_ACCESS) 388 | 389 | #define NF_REQ_ADD_TAIL_BINDING_RULE \ 390 | CTL_CODE(FILE_DEVICE_UNKNOWN, 115, METHOD_BUFFERED, FILE_ANY_ACCESS) 391 | 392 | #define NF_REQ_DELETE_BINDING_RULES \ 393 | CTL_CODE(FILE_DEVICE_UNKNOWN, 116, METHOD_BUFFERED, FILE_ANY_ACCESS) 394 | 395 | #define NF_REQ_ADD_HEAD_RULE_EX \ 396 | CTL_CODE(FILE_DEVICE_UNKNOWN, 117, METHOD_BUFFERED, FILE_ANY_ACCESS) 397 | 398 | #define NF_REQ_ADD_TAIL_RULE_EX \ 399 | CTL_CODE(FILE_DEVICE_UNKNOWN, 118, METHOD_BUFFERED, FILE_ANY_ACCESS) 400 | 401 | #define NF_REQ_ADD_TEMP_RULE_EX \ 402 | CTL_CODE(FILE_DEVICE_UNKNOWN, 119, METHOD_BUFFERED, FILE_ANY_ACCESS) 403 | 404 | #define FSCTL_TCP_BASE FILE_DEVICE_NETWORK 405 | 406 | #define _TCP_CTL_CODE(function, method, access) \ 407 | CTL_CODE(FSCTL_TCP_BASE, function, method, access) 408 | 409 | #define IOCTL_TCP_QUERY_INFORMATION_EX \ 410 | _TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS) 411 | 412 | #define IOCTL_TCP_SET_INFORMATION_EX \ 413 | _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS) 414 | 415 | #endif 416 | 417 | #define FSCTL_DEVCTRL_BASE FILE_DEVICE_NETWORK 418 | 419 | #define _DEVCTRL_CTL_CODE(_Function, _Method, _Access) \ 420 | CTL_CODE(FSCTL_DEVCTRL_BASE, _Function, _Method, _Access) 421 | 422 | #define IOCTL_DEVCTRL_OPEN \ 423 | _DEVCTRL_CTL_CODE(0x200, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 424 | 425 | #endif // _NFDRIVER_H -------------------------------------------------------------------------------- /include/nfevents.h: -------------------------------------------------------------------------------- 1 | // 2 | // NetFilterSDK 3 | // Copyright (C) Vitaly Sidorov 4 | // All rights reserved. 5 | // 6 | // This file is a part of the NetFilter SDK. 7 | // The code and information is provided "as-is" without 8 | // warranty of any kind, either expressed or implied. 9 | // 10 | 11 | 12 | #ifndef _NFEVENTS_H 13 | #define _NFEVENTS_H 14 | 15 | /** 16 | * Return status codes 17 | **/ 18 | typedef enum _NF_STATUS 19 | { 20 | NF_STATUS_SUCCESS = 0, 21 | NF_STATUS_FAIL = -1, 22 | NF_STATUS_INVALID_ENDPOINT_ID = -2, 23 | NF_STATUS_NOT_INITIALIZED = -3, 24 | NF_STATUS_IO_ERROR = -4, 25 | NF_STATUS_REBOOT_REQUIRED = -5 26 | } NF_STATUS; 27 | 28 | #ifndef _C_API 29 | 30 | #define NFAPI_NS nfapi:: 31 | #define NFAPI_CC 32 | 33 | ///////////////////////////////////////////////////////////////////////////////////// 34 | // C++ API 35 | ///////////////////////////////////////////////////////////////////////////////////// 36 | 37 | namespace nfapi 38 | { 39 | #include "nfdriver.h" 40 | 41 | /** 42 | * Filtering events 43 | **/ 44 | class NF_EventHandler 45 | { 46 | public: 47 | 48 | /** 49 | * Called immediately after starting the filtering thread. 50 | * Use this event for thread-specific initialization, e.g. calling 51 | * CoInitialize() etc. 52 | **/ 53 | virtual void threadStart() = 0; 54 | 55 | /** 56 | * Called before stopping the thread. 57 | **/ 58 | virtual void threadEnd() = 0; 59 | 60 | // 61 | // TCP events 62 | // 63 | 64 | /** 65 | * Called before establishing an outgoing TCP connection, 66 | * when NF_INDICATE_CONNECT_REQUESTS flag is specified in an appropriate rule. 67 | * It is possible to change pConnInfo->filteringFlag and pConnInfo->remoteAddress 68 | * in this handler. The changes will be applied to connection. 69 | * @param id Unique connection identifier 70 | * @param pConnInfo Connection parameters, see NF_TCP_CONN_INFO 71 | **/ 72 | virtual void tcpConnectRequest(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo) = 0; 73 | 74 | /** 75 | * Called after successful establishing the incoming or outgoing TCP connection. 76 | * @param id Unique connection identifier 77 | * @param pConnInfo Connection parameters, see NF_TCP_CONN_INFO 78 | **/ 79 | virtual void tcpConnected(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo) = 0; 80 | 81 | /** 82 | * Called after closing the connection identified by id. 83 | * @param id Unique connection identifier 84 | * @param pConnInfo Connection parameters, see NF_TCP_CONN_INFO 85 | **/ 86 | virtual void tcpClosed(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo) = 0; 87 | 88 | /** 89 | * Indicates the buffer received from server. 90 | * @param id Unique connection identifier 91 | * @param buf Pointer to data buffer 92 | * @param len Buffer length 93 | **/ 94 | virtual void tcpReceive(ENDPOINT_ID id, const char * buf, int len) = 0; 95 | 96 | /** 97 | * Indicates the buffer sent from the local socket. 98 | * @param id Unique connection identifier 99 | * @param buf Pointer to data buffer 100 | * @param len Buffer length 101 | **/ 102 | virtual void tcpSend(ENDPOINT_ID id, const char * buf, int len) = 0; 103 | 104 | /** 105 | * Informs that the internal buffer for receives is empty and 106 | * it is possible to call nf_tcpPostReceive for pushing receives 107 | * via specified connection. 108 | * @param id Unique connection identifier 109 | **/ 110 | virtual void tcpCanReceive(ENDPOINT_ID id) = 0; 111 | 112 | /** 113 | * Informs that the internal buffer for sends is empty and 114 | * it is possible to call nf_tcpPostSend for pushing sends 115 | * via specified connection. 116 | * @param id Unique connection identifier 117 | **/ 118 | virtual void tcpCanSend(ENDPOINT_ID id) = 0; 119 | 120 | 121 | // 122 | // UDP events 123 | // 124 | 125 | /** 126 | * Called after creating UDP socket. 127 | * @param id Unique socket identifier 128 | * @param pConnInfo Socket parameters, see NF_UDP_CONN_INFO 129 | **/ 130 | virtual void udpCreated(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo) = 0; 131 | 132 | /** 133 | * Called before establishing an outgoing UDP connection, 134 | * when NF_INDICATE_CONNECT_REQUESTS flag is specified in an appropriate rule. 135 | * It is possible to change pConnReq->filteringFlag and pConnReq->remoteAddress 136 | * in this handler. The changes will be applied to connection. 137 | * @param id Unique connection identifier 138 | * @param pConnInfo Connection parameters, see NF_UDP_CONN_REQUEST 139 | **/ 140 | virtual void udpConnectRequest(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnReq) = 0; 141 | 142 | /** 143 | * Called after closing UDP socket identified by id. 144 | * @param id Unique socket identifier 145 | * @param pConnInfo Socket parameters, see NF_UDP_CONN_INFO 146 | **/ 147 | virtual void udpClosed(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo) = 0; 148 | 149 | /** 150 | * Indicates the buffer received from server. 151 | * @param id Unique socket identifier 152 | * @param options UDP options 153 | * @param remoteAddress Source address 154 | * @param buf Pointer to data buffer 155 | * @param len Buffer length 156 | **/ 157 | virtual void udpReceive(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options) = 0; 158 | 159 | /** 160 | * Indicates the buffer sent from the local socket. 161 | * @param id Unique socket identifier 162 | * @param options UDP options 163 | * @param remoteAddress Destination address 164 | * @param buf Pointer to data buffer 165 | * @param len Buffer length 166 | **/ 167 | virtual void udpSend(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options) = 0; 168 | 169 | /** 170 | * Informs that the internal buffer for receives is empty and 171 | * it is possible to call nf_udpPostReceive for pushing receives 172 | * via specified socket. 173 | * @param id Unique socket identifier 174 | **/ 175 | virtual void udpCanReceive(ENDPOINT_ID id) = 0; 176 | 177 | /** 178 | * Informs that the internal buffer for sends is empty and 179 | * it is possible to call nf_udpPostSend for pushing sends 180 | * via specified socket. 181 | * @param id Unique socket identifier 182 | **/ 183 | virtual void udpCanSend(ENDPOINT_ID id) = 0; 184 | }; 185 | 186 | /** 187 | * IP level filtering events 188 | **/ 189 | class NF_IPEventHandler 190 | { 191 | public: 192 | /** 193 | * Indicates a packet received from server. 194 | * @param buf Pointer to data buffer 195 | * @param len Buffer length 196 | * @param options IP options 197 | **/ 198 | virtual void ipReceive(const char * buf, int len, PNF_IP_PACKET_OPTIONS options) = 0; 199 | 200 | /** 201 | * Indicates a packet sent to server. 202 | * @param buf Pointer to data buffer 203 | * @param len Buffer length 204 | * @param options IP options 205 | **/ 206 | virtual void ipSend(const char * buf, int len, PNF_IP_PACKET_OPTIONS options) = 0; 207 | }; 208 | 209 | #else // _C_API 210 | 211 | #define NFAPI_CC __cdecl 212 | #define NFAPI_NS 213 | 214 | ///////////////////////////////////////////////////////////////////////////////////// 215 | // C API 216 | ///////////////////////////////////////////////////////////////////////////////////// 217 | 218 | #ifdef __cplusplus 219 | extern "C" 220 | { 221 | #endif 222 | 223 | #include "nfdriver.h" 224 | 225 | #pragma pack(push, 1) 226 | 227 | // C analogue of the class NF_EventHandler (see the definition above) 228 | typedef struct _NF_EventHandler 229 | { 230 | void (NFAPI_CC *threadStart)(); 231 | void (NFAPI_CC *threadEnd)(); 232 | void (NFAPI_CC *tcpConnectRequest)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 233 | void (NFAPI_CC *tcpConnected)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 234 | void (NFAPI_CC *tcpClosed)(ENDPOINT_ID id, PNF_TCP_CONN_INFO pConnInfo); 235 | void (NFAPI_CC *tcpReceive)(ENDPOINT_ID id, const char * buf, int len); 236 | void (NFAPI_CC *tcpSend)(ENDPOINT_ID id, const char * buf, int len); 237 | void (NFAPI_CC *tcpCanReceive)(ENDPOINT_ID id); 238 | void (NFAPI_CC *tcpCanSend)(ENDPOINT_ID id); 239 | void (NFAPI_CC *udpCreated)(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 240 | void (NFAPI_CC *udpConnectRequest)(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST pConnReq); 241 | void (NFAPI_CC *udpClosed)(ENDPOINT_ID id, PNF_UDP_CONN_INFO pConnInfo); 242 | void (NFAPI_CC *udpReceive)(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 243 | void (NFAPI_CC *udpSend)(ENDPOINT_ID id, const unsigned char * remoteAddress, const char * buf, int len, PNF_UDP_OPTIONS options); 244 | void (NFAPI_CC *udpCanReceive)(ENDPOINT_ID id); 245 | void (NFAPI_CC *udpCanSend)(ENDPOINT_ID id); 246 | } NF_EventHandler, *PNF_EventHandler; 247 | 248 | // C analogue of the class NF_IPEventHandler (see the definition above) 249 | typedef struct _NF_IPEventHandler 250 | { 251 | void (NFAPI_CC *ipReceive)(const char * buf, int len, PNF_IP_PACKET_OPTIONS options); 252 | void (NFAPI_CC *ipSend)(const char * buf, int len, PNF_IP_PACKET_OPTIONS options); 253 | } NF_IPEventHandler, *PNF_IPEventHandler; 254 | 255 | #pragma pack(pop) 256 | 257 | #endif // _C_API 258 | 259 | 260 | #ifdef __cplusplus 261 | } 262 | #endif 263 | 264 | #endif -------------------------------------------------------------------------------- /lib/nfapi.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XYDsoft/NewProxy/aa7f3246d6eb53d8e69e29958a33b4a6e54d7862/lib/nfapi.exp -------------------------------------------------------------------------------- /lib/nfapi.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XYDsoft/NewProxy/aa7f3246d6eb53d8e69e29958a33b4a6e54d7862/lib/nfapi.lib -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo LDFLAGS: -lwsock32 5 | #cgo LDFLAGS: -lWs2_32 6 | #cgo CFLAGS: -I ./include 7 | #cgo LDFLAGS: -L ./lib -lnfapi 8 | 9 | #include 10 | #include 11 | #include "nfapi.h" 12 | #include "Driver.h" 13 | */ 14 | import "C" 15 | 16 | import ( 17 | "NewProxy/core" 18 | "context" 19 | "net" 20 | "strconv" 21 | "sync" 22 | ) 23 | 24 | const ( 25 | AtypIPv4 = 1 26 | AtypDomainName = 3 27 | AtypIPv6 = 4 28 | AtypSend = 0 29 | AtypRecv = 1 30 | AtypSocks5 = 1 31 | AtypShadowSocks = 2 32 | udpBufSize = 4096 33 | tcpBufSize = 4096 34 | ) 35 | 36 | var proxyMap sync.Map 37 | 38 | //流量统计map 39 | var ProcessInfo = NewProcessMap() 40 | 41 | //tcp map 42 | var tcpmap = NewTcpMap() 43 | 44 | type mccInfo struct { 45 | pid uint64 46 | to int 47 | bytebyte int64 //发送量 48 | } 49 | 50 | type ProxyInfo struct { 51 | ptype int //代理类型 1为socks5 2为Shadowsocks 52 | ip string //代理服务器ip地址 53 | port int //代理服务器端口 54 | user string //账号 55 | passw string //密码 56 | ciph core.Cipher //ss的加密句柄 57 | socks *suMap //socks5 map 58 | ssAddr *net.UDPAddr //ss的代理地址 59 | proxymode int //代理控制 1为代理 TCP 2为代理 UDP 3为 代理TCP+UDP 60 | } 61 | 62 | //流量统计 63 | var mcc = make(chan mccInfo, 1000) 64 | 65 | //流量统计携程 66 | func f(ctx context.Context) { 67 | for { 68 | select { 69 | 70 | case <-ctx.Done(): //退出携程 71 | return 72 | case cs := <-mcc: 73 | 74 | if cs.to == AtypRecv { 75 | ProcessInfo.Add(cs.pid, 0, cs.bytebyte) 76 | } else { 77 | ProcessInfo.Add(cs.pid, cs.bytebyte, 0) 78 | } 79 | } 80 | } 81 | } 82 | 83 | var Cancel func() 84 | 85 | //export Driver_Init 86 | func Driver_Init(aa *C.char, bb C.int, cc *C.char, dd *C.char) C.int { // 87 | 88 | tmeIp := C.GoString(aa) 89 | tmePort := int(bb) 90 | C.setPort(C.int(tmePort), cc, dd) 91 | 92 | var BackCtx context.Context 93 | BackCtx, Cancel = context.WithCancel(context.Background()) 94 | 95 | go tcpLocal(tmeIp+":"+strconv.Itoa(tmePort), BackCtx) 96 | go udpLocal(tmeIp+":", BackCtx) 97 | go f(BackCtx) 98 | 99 | return DriverInit() 100 | } 101 | 102 | //export Driver_Free 103 | func Driver_Free() bool { 104 | 105 | if Cancel != nil { 106 | Cancel() 107 | } 108 | 109 | return DriverFree() 110 | } 111 | 112 | //export GetInfo 113 | func GetInfo(pid C.ulong, c C.int) C.longlong { //1=send 0=recv 114 | 115 | mm := ProcessInfo.Get(uint64(pid)) 116 | if int(c) == 1 { 117 | return C.longlong(mm.send) 118 | 119 | } 120 | return C.longlong(mm.recv) 121 | } 122 | 123 | //export AddProxy 124 | func AddProxy(a1 C.int, a2 C.ulong, a3 *C.char, a4 C.int, a5 *C.char, a6 *C.char, a7 C.int) bool { 125 | ptype := int(a1) 126 | pid := uint64(a2) 127 | ip := C.GoString(a3) 128 | port := int(a4) 129 | user := C.GoString(a5) 130 | pass := C.GoString(a6) 131 | modes := int(a7) 132 | 133 | //进程id存在 134 | if _, ok := proxyMap.Load(pid); ok { 135 | return false 136 | } 137 | 138 | switch ptype { 139 | 140 | case AtypSocks5: 141 | 142 | p := ProxyInfo{ 143 | ptype: AtypSocks5, 144 | ip: ip, 145 | port: port, 146 | user: user, 147 | passw: pass, 148 | ciph: nil, 149 | socks: NewSuMap(), 150 | ssAddr: nil, 151 | proxymode: modes, 152 | } 153 | 154 | proxyMap.Store(pid, p) 155 | return true 156 | 157 | case AtypShadowSocks: 158 | 159 | var key []byte 160 | ciph, err := core.PickCipher(user, key, pass) 161 | if err != nil { 162 | return false 163 | } 164 | 165 | mAddr, err := net.ResolveUDPAddr("udp", ip+":"+strconv.Itoa(port)) 166 | if err != nil { 167 | return false 168 | } 169 | p := ProxyInfo{ 170 | ptype: AtypShadowSocks, 171 | ip: ip, 172 | port: port, 173 | user: user, 174 | passw: pass, 175 | ciph: ciph, 176 | socks: nil, 177 | ssAddr: mAddr, 178 | proxymode: modes, 179 | } 180 | 181 | proxyMap.Store(pid, p) 182 | 183 | return true 184 | default: 185 | return false 186 | } 187 | return false 188 | } 189 | 190 | //export DelteProxy 191 | func DelteProxy(pid C.ulong) bool { 192 | 193 | id := uint64(pid) 194 | 195 | //查找进程对应的代理信息 196 | prs, ok := proxyMap.Load(id) 197 | if !ok { 198 | return false 199 | } 200 | pProxy, ok := prs.(ProxyInfo) 201 | if !ok { 202 | return false 203 | } 204 | //关闭socks5握手 205 | if pProxy.ptype == AtypSocks5 { 206 | go pProxy.socks.DelAll() 207 | 208 | } 209 | 210 | //删除代理信息 211 | proxyMap.Delete(id) 212 | //删除流量统计 213 | ProcessInfo.Del(id) 214 | return true 215 | 216 | } 217 | 218 | var DnsAddr *net.UDPAddr //dns 地址 219 | var DnsOut int //dns超时时间 220 | 221 | var DnsPacket core.Cipher //dns代理加密方式 222 | var DnsPAddr *net.UDPAddr //dns代理服务器 223 | 224 | //export SetDns 225 | func SetDns(a1 *C.char, a2 C.int, a3 C.int) bool { 226 | 227 | return false 228 | 229 | sAddr := C.GoString(a1) 230 | sPort := int(a2) 231 | out := int(a3) 232 | 233 | if sAddr == "" { 234 | DnsAddr = nil 235 | return true 236 | } 237 | 238 | var err error 239 | DnsOut = out 240 | DnsAddr, err = net.ResolveUDPAddr("udp", sAddr+":"+strconv.Itoa(sPort)) 241 | if err != nil { 242 | return false 243 | } 244 | return true 245 | } 246 | 247 | //export SetDnsProxy 248 | func SetDnsProxy(a1 *C.char, a2 C.int, a3 *C.char, a4 *C.char) bool { 249 | 250 | return false 251 | 252 | sAddr := C.GoString(a1) 253 | sPort := int(a2) 254 | user := C.GoString(a3) 255 | pass := C.GoString(a4) 256 | 257 | if sAddr == "" { 258 | DnsPAddr = nil 259 | return true 260 | } 261 | 262 | var key []byte 263 | var err error 264 | DnsPacket, err = core.PickCipher(user, key, pass) 265 | if err != nil { 266 | return false 267 | } 268 | 269 | DnsPAddr, err = net.ResolveUDPAddr("udp", sAddr+":"+strconv.Itoa(sPort)) 270 | if err != nil { 271 | return false 272 | } 273 | 274 | return true 275 | 276 | } 277 | 278 | func main() { 279 | // Need a main function to make CGO compile package as C shared library 280 | 281 | } 282 | -------------------------------------------------------------------------------- /shadowaead/cipher.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/sha1" 7 | "io" 8 | "strconv" 9 | 10 | "golang.org/x/crypto/chacha20poly1305" 11 | "golang.org/x/crypto/hkdf" 12 | ) 13 | 14 | type Cipher interface { 15 | KeySize() int 16 | SaltSize() int 17 | Encrypter(salt []byte) (cipher.AEAD, error) 18 | Decrypter(salt []byte) (cipher.AEAD, error) 19 | } 20 | 21 | type KeySizeError int 22 | 23 | func (e KeySizeError) Error() string { 24 | return "key size error: need " + strconv.Itoa(int(e)) + " bytes" 25 | } 26 | 27 | func hkdfSHA1(secret, salt, info, outkey []byte) { 28 | r := hkdf.New(sha1.New, secret, salt, info) 29 | if _, err := io.ReadFull(r, outkey); err != nil { 30 | panic(err) // should never happen 31 | } 32 | } 33 | 34 | type metaCipher struct { 35 | psk []byte 36 | makeAEAD func(key []byte) (cipher.AEAD, error) 37 | } 38 | 39 | func (a *metaCipher) KeySize() int { return len(a.psk) } 40 | func (a *metaCipher) SaltSize() int { 41 | if ks := a.KeySize(); ks > 16 { 42 | return ks 43 | } 44 | return 16 45 | } 46 | func (a *metaCipher) Encrypter(salt []byte) (cipher.AEAD, error) { 47 | subkey := make([]byte, a.KeySize()) 48 | hkdfSHA1(a.psk, salt, []byte("ss-subkey"), subkey) 49 | return a.makeAEAD(subkey) 50 | } 51 | func (a *metaCipher) Decrypter(salt []byte) (cipher.AEAD, error) { 52 | subkey := make([]byte, a.KeySize()) 53 | hkdfSHA1(a.psk, salt, []byte("ss-subkey"), subkey) 54 | return a.makeAEAD(subkey) 55 | } 56 | 57 | func aesGCM(key []byte) (cipher.AEAD, error) { 58 | blk, err := aes.NewCipher(key) 59 | if err != nil { 60 | return nil, err 61 | } 62 | return cipher.NewGCM(blk) 63 | } 64 | 65 | // AESGCM creates a new Cipher with a pre-shared key. len(psk) must be 66 | // one of 16, 24, or 32 to select AES-128/196/256-GCM. 67 | func AESGCM(psk []byte) (Cipher, error) { 68 | switch l := len(psk); l { 69 | case 16, 24, 32: // AES 128/196/256 70 | default: 71 | return nil, aes.KeySizeError(l) 72 | } 73 | return &metaCipher{psk: psk, makeAEAD: aesGCM}, nil 74 | } 75 | 76 | // Chacha20Poly1305 creates a new Cipher with a pre-shared key. len(psk) 77 | // must be 32. 78 | func Chacha20Poly1305(psk []byte) (Cipher, error) { 79 | if len(psk) != chacha20poly1305.KeySize { 80 | return nil, KeySizeError(chacha20poly1305.KeySize) 81 | } 82 | return &metaCipher{psk: psk, makeAEAD: chacha20poly1305.New}, nil 83 | } 84 | -------------------------------------------------------------------------------- /shadowaead/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package shadowaead implements a simple AEAD-protected secure protocol. 3 | 4 | In general, there are two types of connections: stream-oriented and packet-oriented. 5 | Stream-oriented connections (e.g. TCP) assume reliable and orderly delivery of bytes. 6 | Packet-oriented connections (e.g. UDP) assume unreliable and out-of-order delivery of packets, 7 | where each packet is either delivered intact or lost. 8 | 9 | An encrypted stream starts with a random salt to derive a session key, followed by any number of 10 | encrypted records. Each encrypted record has the following structure: 11 | 12 | [encrypted payload length] 13 | [payload length tag] 14 | [encrypted payload] 15 | [payload tag] 16 | 17 | Payload length is 2-byte unsigned big-endian integer capped at 0x3FFF (16383). 18 | The higher 2 bits are reserved and must be set to zero. The first AEAD encrypt/decrypt 19 | operation uses a counting nonce starting from 0. After each encrypt/decrypt operation, 20 | the nonce is incremented by one as if it were an unsigned little-endian integer. 21 | 22 | 23 | Each encrypted packet transmitted on a packet-oriented connection has the following structure: 24 | 25 | [random salt] 26 | [encrypted payload] 27 | [payload tag] 28 | 29 | The salt is used to derive a subkey to initiate an AEAD. Packets are encrypted/decrypted independently 30 | using zero nonce. 31 | 32 | In both stream-oriented and packet-oriented connections, length of nonce and tag varies 33 | depending on which AEAD is used. Salt should be at least 16-byte long. 34 | */ 35 | package shadowaead 36 | -------------------------------------------------------------------------------- /shadowaead/packet.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "crypto/rand" 5 | "errors" 6 | "io" 7 | "net" 8 | "sync" 9 | ) 10 | 11 | // ErrShortPacket means that the packet is too short for a valid encrypted packet. 12 | var ErrShortPacket = errors.New("short packet") 13 | 14 | var _zerononce [128]byte // read-only. 128 bytes is more than enough. 15 | 16 | // Pack encrypts plaintext using Cipher with a randomly generated salt and 17 | // returns a slice of dst containing the encrypted packet and any error occurred. 18 | // Ensure len(dst) >= ciph.SaltSize() + len(plaintext) + aead.Overhead(). 19 | func Pack(dst, plaintext []byte, ciph Cipher) ([]byte, error) { 20 | saltSize := ciph.SaltSize() 21 | salt := dst[:saltSize] 22 | if _, err := io.ReadFull(rand.Reader, salt); err != nil { 23 | return nil, err 24 | } 25 | 26 | aead, err := ciph.Encrypter(salt) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | if len(dst) < saltSize+len(plaintext)+aead.Overhead() { 32 | return nil, io.ErrShortBuffer 33 | } 34 | b := aead.Seal(dst[saltSize:saltSize], _zerononce[:aead.NonceSize()], plaintext, nil) 35 | return dst[:saltSize+len(b)], nil 36 | } 37 | 38 | // Unpack decrypts pkt using Cipher and returns a slice of dst containing the decrypted payload and any error occurred. 39 | // Ensure len(dst) >= len(pkt) - aead.SaltSize() - aead.Overhead(). 40 | func Unpack(dst, pkt []byte, ciph Cipher) ([]byte, error) { 41 | saltSize := ciph.SaltSize() 42 | if len(pkt) < saltSize { 43 | return nil, ErrShortPacket 44 | } 45 | salt := pkt[:saltSize] 46 | aead, err := ciph.Decrypter(salt) 47 | if err != nil { 48 | return nil, err 49 | } 50 | if len(pkt) < saltSize+aead.Overhead() { 51 | return nil, ErrShortPacket 52 | } 53 | if saltSize+len(dst)+aead.Overhead() < len(pkt) { 54 | return nil, io.ErrShortBuffer 55 | } 56 | b, err := aead.Open(dst[:0], _zerononce[:aead.NonceSize()], pkt[saltSize:], nil) 57 | return b, err 58 | } 59 | 60 | type packetConn struct { 61 | net.PacketConn 62 | Cipher 63 | sync.Mutex 64 | buf []byte // write lock 65 | } 66 | 67 | // NewPacketConn wraps a net.PacketConn with cipher 68 | func NewPacketConn(c net.PacketConn, ciph Cipher) net.PacketConn { 69 | const maxPacketSize = 64 * 1024 70 | return &packetConn{PacketConn: c, Cipher: ciph, buf: make([]byte, maxPacketSize)} 71 | } 72 | 73 | // WriteTo encrypts b and write to addr using the embedded PacketConn. 74 | func (c *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) { 75 | c.Lock() 76 | defer c.Unlock() 77 | buf, err := Pack(c.buf, b, c) 78 | if err != nil { 79 | return 0, err 80 | } 81 | _, err = c.PacketConn.WriteTo(buf, addr) 82 | return len(b), err 83 | } 84 | 85 | // ReadFrom reads from the embedded PacketConn and decrypts into b. 86 | func (c *packetConn) ReadFrom(b []byte) (int, net.Addr, error) { 87 | n, addr, err := c.PacketConn.ReadFrom(b) 88 | if err != nil { 89 | return n, addr, err 90 | } 91 | bb, err := Unpack(b[c.Cipher.SaltSize():], b[:n], c) 92 | if err != nil { 93 | return n, addr, err 94 | } 95 | copy(b, bb) 96 | return len(bb), addr, err 97 | } 98 | -------------------------------------------------------------------------------- /shadowaead/stream.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "bytes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "io" 8 | "net" 9 | ) 10 | 11 | // payloadSizeMask is the maximum size of payload in bytes. 12 | const payloadSizeMask = 0x3FFF // 16*1024 - 1 13 | 14 | type writer struct { 15 | io.Writer 16 | cipher.AEAD 17 | nonce []byte 18 | buf []byte 19 | } 20 | 21 | // NewWriter wraps an io.Writer with AEAD encryption. 22 | func NewWriter(w io.Writer, aead cipher.AEAD) io.Writer { return newWriter(w, aead) } 23 | 24 | func newWriter(w io.Writer, aead cipher.AEAD) *writer { 25 | return &writer{ 26 | Writer: w, 27 | AEAD: aead, 28 | buf: make([]byte, 2+aead.Overhead()+payloadSizeMask+aead.Overhead()), 29 | nonce: make([]byte, aead.NonceSize()), 30 | } 31 | } 32 | 33 | // Write encrypts b and writes to the embedded io.Writer. 34 | func (w *writer) Write(b []byte) (int, error) { 35 | n, err := w.ReadFrom(bytes.NewBuffer(b)) 36 | return int(n), err 37 | } 38 | 39 | // ReadFrom reads from the given io.Reader until EOF or error, encrypts and 40 | // writes to the embedded io.Writer. Returns number of bytes read from r and 41 | // any error encountered. 42 | func (w *writer) ReadFrom(r io.Reader) (n int64, err error) { 43 | for { 44 | buf := w.buf 45 | payloadBuf := buf[2+w.Overhead() : 2+w.Overhead()+payloadSizeMask] 46 | nr, er := r.Read(payloadBuf) 47 | 48 | if nr > 0 { 49 | n += int64(nr) 50 | buf = buf[:2+w.Overhead()+nr+w.Overhead()] 51 | payloadBuf = payloadBuf[:nr] 52 | buf[0], buf[1] = byte(nr>>8), byte(nr) // big-endian payload size 53 | w.Seal(buf[:0], w.nonce, buf[:2], nil) 54 | increment(w.nonce) 55 | 56 | w.Seal(payloadBuf[:0], w.nonce, payloadBuf, nil) 57 | increment(w.nonce) 58 | 59 | _, ew := w.Writer.Write(buf) 60 | if ew != nil { 61 | err = ew 62 | break 63 | } 64 | } 65 | 66 | if er != nil { 67 | if er != io.EOF { // ignore EOF as per io.ReaderFrom contract 68 | err = er 69 | } 70 | break 71 | } 72 | } 73 | 74 | return n, err 75 | } 76 | 77 | type reader struct { 78 | io.Reader 79 | cipher.AEAD 80 | nonce []byte 81 | buf []byte 82 | leftover []byte 83 | } 84 | 85 | // NewReader wraps an io.Reader with AEAD decryption. 86 | func NewReader(r io.Reader, aead cipher.AEAD) io.Reader { return newReader(r, aead) } 87 | 88 | func newReader(r io.Reader, aead cipher.AEAD) *reader { 89 | return &reader{ 90 | Reader: r, 91 | AEAD: aead, 92 | buf: make([]byte, payloadSizeMask+aead.Overhead()), 93 | nonce: make([]byte, aead.NonceSize()), 94 | } 95 | } 96 | 97 | // read and decrypt a record into the internal buffer. Return decrypted payload length and any error encountered. 98 | func (r *reader) read() (int, error) { 99 | // decrypt payload size 100 | buf := r.buf[:2+r.Overhead()] 101 | _, err := io.ReadFull(r.Reader, buf) 102 | if err != nil { 103 | return 0, err 104 | } 105 | 106 | _, err = r.Open(buf[:0], r.nonce, buf, nil) 107 | increment(r.nonce) 108 | if err != nil { 109 | return 0, err 110 | } 111 | 112 | size := (int(buf[0])<<8 + int(buf[1])) & payloadSizeMask 113 | 114 | // decrypt payload 115 | buf = r.buf[:size+r.Overhead()] 116 | _, err = io.ReadFull(r.Reader, buf) 117 | if err != nil { 118 | return 0, err 119 | } 120 | 121 | _, err = r.Open(buf[:0], r.nonce, buf, nil) 122 | increment(r.nonce) 123 | if err != nil { 124 | return 0, err 125 | } 126 | 127 | return size, nil 128 | } 129 | 130 | // Read reads from the embedded io.Reader, decrypts and writes to b. 131 | func (r *reader) Read(b []byte) (int, error) { 132 | // copy decrypted bytes (if any) from previous record first 133 | if len(r.leftover) > 0 { 134 | n := copy(b, r.leftover) 135 | r.leftover = r.leftover[n:] 136 | return n, nil 137 | } 138 | 139 | n, err := r.read() 140 | m := copy(b, r.buf[:n]) 141 | if m < n { // insufficient len(b), keep leftover for next read 142 | r.leftover = r.buf[m:n] 143 | } 144 | return m, err 145 | } 146 | 147 | // WriteTo reads from the embedded io.Reader, decrypts and writes to w until 148 | // there's no more data to write or when an error occurs. Return number of 149 | // bytes written to w and any error encountered. 150 | func (r *reader) WriteTo(w io.Writer) (n int64, err error) { 151 | // write decrypted bytes left over from previous record 152 | for len(r.leftover) > 0 { 153 | nw, ew := w.Write(r.leftover) 154 | r.leftover = r.leftover[nw:] 155 | n += int64(nw) 156 | if ew != nil { 157 | return n, ew 158 | } 159 | } 160 | 161 | for { 162 | nr, er := r.read() 163 | if nr > 0 { 164 | nw, ew := w.Write(r.buf[:nr]) 165 | n += int64(nw) 166 | 167 | if ew != nil { 168 | err = ew 169 | break 170 | } 171 | } 172 | 173 | if er != nil { 174 | if er != io.EOF { // ignore EOF as per io.Copy contract (using src.WriteTo shortcut) 175 | err = er 176 | } 177 | break 178 | } 179 | } 180 | 181 | return n, err 182 | } 183 | 184 | // increment little-endian encoded unsigned integer b. Wrap around on overflow. 185 | func increment(b []byte) { 186 | for i := range b { 187 | b[i]++ 188 | if b[i] != 0 { 189 | return 190 | } 191 | } 192 | } 193 | 194 | type streamConn struct { 195 | net.Conn 196 | Cipher 197 | r *reader 198 | w *writer 199 | } 200 | 201 | func (c *streamConn) initReader() error { 202 | salt := make([]byte, c.SaltSize()) 203 | if _, err := io.ReadFull(c.Conn, salt); err != nil { 204 | return err 205 | } 206 | 207 | aead, err := c.Decrypter(salt) 208 | if err != nil { 209 | return err 210 | } 211 | 212 | c.r = newReader(c.Conn, aead) 213 | return nil 214 | } 215 | 216 | func (c *streamConn) Read(b []byte) (int, error) { 217 | if c.r == nil { 218 | if err := c.initReader(); err != nil { 219 | return 0, err 220 | } 221 | } 222 | return c.r.Read(b) 223 | } 224 | 225 | func (c *streamConn) WriteTo(w io.Writer) (int64, error) { 226 | if c.r == nil { 227 | if err := c.initReader(); err != nil { 228 | return 0, err 229 | } 230 | } 231 | return c.r.WriteTo(w) 232 | } 233 | 234 | func (c *streamConn) initWriter() error { 235 | salt := make([]byte, c.SaltSize()) 236 | if _, err := io.ReadFull(rand.Reader, salt); err != nil { 237 | return err 238 | } 239 | aead, err := c.Encrypter(salt) 240 | if err != nil { 241 | return err 242 | } 243 | _, err = c.Conn.Write(salt) 244 | if err != nil { 245 | return err 246 | } 247 | c.w = newWriter(c.Conn, aead) 248 | return nil 249 | } 250 | 251 | func (c *streamConn) Write(b []byte) (int, error) { 252 | if c.w == nil { 253 | if err := c.initWriter(); err != nil { 254 | return 0, err 255 | } 256 | } 257 | return c.w.Write(b) 258 | } 259 | 260 | func (c *streamConn) ReadFrom(r io.Reader) (int64, error) { 261 | if c.w == nil { 262 | if err := c.initWriter(); err != nil { 263 | return 0, err 264 | } 265 | } 266 | return c.w.ReadFrom(r) 267 | } 268 | 269 | // NewConn wraps a stream-oriented net.Conn with cipher. 270 | func NewConn(c net.Conn, ciph Cipher) net.Conn { return &streamConn{Conn: c, Cipher: ciph} } 271 | -------------------------------------------------------------------------------- /shadowstream/cipher.go: -------------------------------------------------------------------------------- 1 | package shadowstream 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "strconv" 7 | 8 | "github.com/aead/chacha20" 9 | "github.com/aead/chacha20/chacha" 10 | ) 11 | 12 | // Cipher generates a pair of stream ciphers for encryption and decryption. 13 | type Cipher interface { 14 | IVSize() int 15 | Encrypter(iv []byte) cipher.Stream 16 | Decrypter(iv []byte) cipher.Stream 17 | } 18 | 19 | type KeySizeError int 20 | 21 | func (e KeySizeError) Error() string { 22 | return "key size error: need " + strconv.Itoa(int(e)) + " bytes" 23 | } 24 | 25 | // CTR mode 26 | type ctrStream struct{ cipher.Block } 27 | 28 | func (b *ctrStream) IVSize() int { return b.BlockSize() } 29 | func (b *ctrStream) Decrypter(iv []byte) cipher.Stream { return b.Encrypter(iv) } 30 | func (b *ctrStream) Encrypter(iv []byte) cipher.Stream { return cipher.NewCTR(b, iv) } 31 | 32 | func AESCTR(key []byte) (Cipher, error) { 33 | blk, err := aes.NewCipher(key) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return &ctrStream{blk}, nil 38 | } 39 | 40 | // CFB mode 41 | type cfbStream struct{ cipher.Block } 42 | 43 | func (b *cfbStream) IVSize() int { return b.BlockSize() } 44 | func (b *cfbStream) Decrypter(iv []byte) cipher.Stream { return cipher.NewCFBDecrypter(b, iv) } 45 | func (b *cfbStream) Encrypter(iv []byte) cipher.Stream { return cipher.NewCFBEncrypter(b, iv) } 46 | 47 | func AESCFB(key []byte) (Cipher, error) { 48 | blk, err := aes.NewCipher(key) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return &cfbStream{blk}, nil 53 | } 54 | 55 | // IETF-variant of chacha20 56 | type chacha20ietfkey []byte 57 | 58 | func (k chacha20ietfkey) IVSize() int { return chacha.INonceSize } 59 | func (k chacha20ietfkey) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } 60 | func (k chacha20ietfkey) Encrypter(iv []byte) cipher.Stream { 61 | ciph, err := chacha20.NewCipher(iv, k) 62 | if err != nil { 63 | panic(err) // should never happen 64 | } 65 | return ciph 66 | } 67 | 68 | func Chacha20IETF(key []byte) (Cipher, error) { 69 | if len(key) != chacha.KeySize { 70 | return nil, KeySizeError(chacha.KeySize) 71 | } 72 | return chacha20ietfkey(key), nil 73 | } 74 | 75 | type xchacha20key []byte 76 | 77 | func (k xchacha20key) IVSize() int { return chacha.XNonceSize } 78 | func (k xchacha20key) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } 79 | func (k xchacha20key) Encrypter(iv []byte) cipher.Stream { 80 | ciph, err := chacha20.NewCipher(iv, k) 81 | if err != nil { 82 | panic(err) // should never happen 83 | } 84 | return ciph 85 | } 86 | 87 | func Xchacha20(key []byte) (Cipher, error) { 88 | if len(key) != chacha.KeySize { 89 | return nil, KeySizeError(chacha.KeySize) 90 | } 91 | return xchacha20key(key), nil 92 | } 93 | -------------------------------------------------------------------------------- /shadowstream/doc.go: -------------------------------------------------------------------------------- 1 | // Package shadowstream implements the original Shadowsocks protocol protected by stream cipher. 2 | package shadowstream 3 | -------------------------------------------------------------------------------- /shadowstream/packet.go: -------------------------------------------------------------------------------- 1 | package shadowstream 2 | 3 | import ( 4 | "crypto/rand" 5 | "errors" 6 | "io" 7 | "net" 8 | "sync" 9 | ) 10 | 11 | // ErrShortPacket means the packet is too short to be a valid encrypted packet. 12 | var ErrShortPacket = errors.New("short packet") 13 | 14 | // Pack encrypts plaintext using stream cipher s and a random IV. 15 | // Returns a slice of dst containing random IV and ciphertext. 16 | // Ensure len(dst) >= s.IVSize() + len(plaintext). 17 | func Pack(dst, plaintext []byte, s Cipher) ([]byte, error) { 18 | if len(dst) < s.IVSize()+len(plaintext) { 19 | return nil, io.ErrShortBuffer 20 | } 21 | iv := dst[:s.IVSize()] 22 | _, err := io.ReadFull(rand.Reader, iv) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | s.Encrypter(iv).XORKeyStream(dst[len(iv):], plaintext) 28 | return dst[:len(iv)+len(plaintext)], nil 29 | } 30 | 31 | // Unpack decrypts pkt using stream cipher s. 32 | // Returns a slice of dst containing decrypted plaintext. 33 | func Unpack(dst, pkt []byte, s Cipher) ([]byte, error) { 34 | if len(pkt) < s.IVSize() { 35 | return nil, ErrShortPacket 36 | } 37 | 38 | if len(dst) < len(pkt)-s.IVSize() { 39 | return nil, io.ErrShortBuffer 40 | } 41 | iv := pkt[:s.IVSize()] 42 | s.Decrypter(iv).XORKeyStream(dst, pkt[len(iv):]) 43 | return dst[:len(pkt)-len(iv)], nil 44 | } 45 | 46 | type packetConn struct { 47 | net.PacketConn 48 | Cipher 49 | buf []byte 50 | sync.Mutex // write lock 51 | } 52 | 53 | // NewPacketConn wraps a net.PacketConn with stream cipher encryption/decryption. 54 | func NewPacketConn(c net.PacketConn, ciph Cipher) net.PacketConn { 55 | return &packetConn{PacketConn: c, Cipher: ciph, buf: make([]byte, 64*1024)} 56 | } 57 | 58 | func (c *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) { 59 | c.Lock() 60 | defer c.Unlock() 61 | buf, err := Pack(c.buf, b, c.Cipher) 62 | if err != nil { 63 | return 0, err 64 | } 65 | _, err = c.PacketConn.WriteTo(buf, addr) 66 | return len(b), err 67 | } 68 | 69 | func (c *packetConn) ReadFrom(b []byte) (int, net.Addr, error) { 70 | n, addr, err := c.PacketConn.ReadFrom(b) 71 | if err != nil { 72 | return n, addr, err 73 | } 74 | bb, err := Unpack(b[c.IVSize():], b[:n], c.Cipher) 75 | if err != nil { 76 | return n, addr, err 77 | } 78 | copy(b, bb) 79 | return len(bb), addr, err 80 | } 81 | -------------------------------------------------------------------------------- /shadowstream/stream.go: -------------------------------------------------------------------------------- 1 | package shadowstream 2 | 3 | import ( 4 | "bytes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "io" 8 | "net" 9 | ) 10 | 11 | const bufSize = 32 * 1024 12 | 13 | type writer struct { 14 | io.Writer 15 | cipher.Stream 16 | buf []byte 17 | } 18 | 19 | // NewWriter wraps an io.Writer with stream cipher encryption. 20 | func NewWriter(w io.Writer, s cipher.Stream) io.Writer { 21 | return &writer{Writer: w, Stream: s, buf: make([]byte, bufSize)} 22 | } 23 | 24 | func (w *writer) ReadFrom(r io.Reader) (n int64, err error) { 25 | for { 26 | buf := w.buf 27 | nr, er := r.Read(buf) 28 | if nr > 0 { 29 | n += int64(nr) 30 | buf = buf[:nr] 31 | w.XORKeyStream(buf, buf) 32 | _, ew := w.Writer.Write(buf) 33 | if ew != nil { 34 | err = ew 35 | return 36 | } 37 | } 38 | 39 | if er != nil { 40 | if er != io.EOF { // ignore EOF as per io.ReaderFrom contract 41 | err = er 42 | } 43 | return 44 | } 45 | } 46 | } 47 | 48 | func (w *writer) Write(b []byte) (int, error) { 49 | n, err := w.ReadFrom(bytes.NewBuffer(b)) 50 | return int(n), err 51 | } 52 | 53 | type reader struct { 54 | io.Reader 55 | cipher.Stream 56 | buf []byte 57 | } 58 | 59 | // NewReader wraps an io.Reader with stream cipher decryption. 60 | func NewReader(r io.Reader, s cipher.Stream) io.Reader { 61 | return &reader{Reader: r, Stream: s, buf: make([]byte, bufSize)} 62 | } 63 | 64 | func (r *reader) Read(b []byte) (int, error) { 65 | 66 | n, err := r.Reader.Read(b) 67 | if err != nil { 68 | return 0, err 69 | } 70 | b = b[:n] 71 | r.XORKeyStream(b, b) 72 | return n, nil 73 | } 74 | 75 | func (r *reader) WriteTo(w io.Writer) (n int64, err error) { 76 | for { 77 | buf := r.buf 78 | nr, er := r.Read(buf) 79 | if nr > 0 { 80 | nw, ew := w.Write(buf[:nr]) 81 | n += int64(nw) 82 | 83 | if ew != nil { 84 | err = ew 85 | return 86 | } 87 | } 88 | 89 | if er != nil { 90 | if er != io.EOF { // ignore EOF as per io.Copy contract (using src.WriteTo shortcut) 91 | err = er 92 | } 93 | return 94 | } 95 | } 96 | } 97 | 98 | type conn struct { 99 | net.Conn 100 | Cipher 101 | r *reader 102 | w *writer 103 | } 104 | 105 | // NewConn wraps a stream-oriented net.Conn with stream cipher encryption/decryption. 106 | func NewConn(c net.Conn, ciph Cipher) net.Conn { 107 | return &conn{Conn: c, Cipher: ciph} 108 | } 109 | 110 | func (c *conn) initReader() error { 111 | if c.r == nil { 112 | buf := make([]byte, bufSize) 113 | iv := buf[:c.IVSize()] 114 | if _, err := io.ReadFull(c.Conn, iv); err != nil { 115 | return err 116 | } 117 | c.r = &reader{Reader: c.Conn, Stream: c.Decrypter(iv), buf: buf} 118 | } 119 | return nil 120 | } 121 | 122 | func (c *conn) Read(b []byte) (int, error) { 123 | if c.r == nil { 124 | if err := c.initReader(); err != nil { 125 | return 0, err 126 | } 127 | } 128 | return c.r.Read(b) 129 | } 130 | 131 | func (c *conn) WriteTo(w io.Writer) (int64, error) { 132 | if c.r == nil { 133 | if err := c.initReader(); err != nil { 134 | return 0, err 135 | } 136 | } 137 | return c.r.WriteTo(w) 138 | } 139 | 140 | func (c *conn) initWriter() error { 141 | if c.w == nil { 142 | buf := make([]byte, bufSize) 143 | iv := buf[:c.IVSize()] 144 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 145 | return err 146 | } 147 | if _, err := c.Conn.Write(iv); err != nil { 148 | return err 149 | } 150 | c.w = &writer{Writer: c.Conn, Stream: c.Encrypter(iv), buf: buf} 151 | } 152 | return nil 153 | } 154 | 155 | func (c *conn) Write(b []byte) (int, error) { 156 | if c.w == nil { 157 | if err := c.initWriter(); err != nil { 158 | return 0, err 159 | } 160 | } 161 | return c.w.Write(b) 162 | } 163 | 164 | func (c *conn) ReadFrom(r io.Reader) (int64, error) { 165 | if c.w == nil { 166 | if err := c.initWriter(); err != nil { 167 | return 0, err 168 | } 169 | } 170 | return c.w.ReadFrom(r) 171 | } 172 | -------------------------------------------------------------------------------- /tcp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | // 监听本地 11 | func tcpLocal(addr string, ctx context.Context) { 12 | l, err := net.Listen("tcp", addr) 13 | if err != nil { 14 | return 15 | } 16 | defer l.Close() 17 | 18 | //循环接受连接 19 | for { 20 | select { 21 | 22 | case <-ctx.Done(): 23 | return 24 | default: 25 | c, err := l.Accept() 26 | if err != nil { 27 | continue 28 | } 29 | go tcpShakehands(c) 30 | } 31 | } 32 | } 33 | 34 | //tcp握手 35 | func tcpShakehands(c net.Conn) { 36 | 37 | defer c.Close() 38 | c.(*net.TCPConn).SetKeepAlive(true) 39 | 40 | //查找对应远程地址 41 | localPort := c.RemoteAddr().(*net.TCPAddr).Port 42 | 43 | //先找出这条连接对应的进程id 和目标信息 44 | pInfo, ok := tcpmap.Get(localPort) 45 | if ok != true { 46 | return 47 | } 48 | 49 | tcpmap.Del(localPort) 50 | 51 | //查找进程对应的代理信息 52 | prs, ok := proxyMap.Load(pInfo.pid) 53 | if !ok { 54 | return 55 | } 56 | pProxy, ok := prs.(ProxyInfo) 57 | if !ok { 58 | return 59 | } 60 | 61 | server := pProxy.ip + ":" + strconv.Itoa(pProxy.port) 62 | 63 | //连接代理 64 | rc, err := net.DialTimeout("tcp", server, 5*time.Second) 65 | if err != nil { 66 | return 67 | } 68 | defer rc.Close() 69 | rc.(*net.TCPConn).SetKeepAlive(true) 70 | 71 | switch pProxy.ptype { 72 | 73 | case AtypSocks5: //Socks5 74 | if err := Socks5Tcp(rc, pProxy.user, pProxy.passw, pInfo.ip); err != nil { 75 | return 76 | } 77 | 78 | case AtypShadowSocks: //Shadowsocks 79 | 80 | rc = pProxy.ciph.StreamConn(rc) 81 | //ss协议发送头信息 82 | if _, Perr := rc.Write(pInfo.ip); Perr != nil { 83 | return 84 | } 85 | 86 | default: 87 | return 88 | } 89 | 90 | //拷贝数据流 完成tcp对接 91 | _, _, err = relay(rc, c, pInfo.pid) 92 | if err != nil { 93 | if err, ok := err.(net.Error); ok && err.Timeout() { 94 | return // ignore i/o timeout 95 | } 96 | } 97 | } 98 | 99 | // 转发数据 100 | func relay(left, right net.Conn, pid uint64) (int64, int64, error) { 101 | type res struct { 102 | N int64 103 | Err error 104 | } 105 | ch := make(chan res) 106 | 107 | go func() { //recv 108 | n, err := Copy(right, left, AtypRecv, pid) 109 | right.SetDeadline(time.Now()) // wake up the other goroutine blocking on right 110 | left.SetDeadline(time.Now()) // wake up the other goroutine blocking on left 111 | ch <- res{n, err} 112 | }() 113 | 114 | //send 115 | n, err := Copy(left, right, AtypSend, pid) 116 | right.SetDeadline(time.Now()) // wake up the other goroutine blocking on right 117 | left.SetDeadline(time.Now()) // wake up the other goroutine blocking on left 118 | rs := <-ch 119 | 120 | if err == nil { 121 | err = rs.Err 122 | } 123 | return n, rs.N, err 124 | } 125 | 126 | func Copy(dst, src net.Conn, sc int, pid uint64) (written int64, err error) { 127 | buf := make([]byte, tcpBufSize) 128 | 129 | for { 130 | nr, er := src.Read(buf) 131 | if er != nil { 132 | err = er 133 | break 134 | } 135 | 136 | if nr > 0 { 137 | _, ew := dst.Write(buf[0:nr]) 138 | if ew != nil { 139 | err = ew 140 | break 141 | } 142 | } 143 | //流量统计 144 | mcc <- mccInfo{pid: pid, to: sc, bytebyte: int64(nr)} 145 | 146 | } 147 | return written, err 148 | } 149 | -------------------------------------------------------------------------------- /udp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo CFLAGS: -I ./include 5 | #cgo LDFLAGS: -L ./lib -lnfapi 6 | 7 | #include 8 | #include 9 | #include "nfapi.h" 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "net" 17 | "sync" 18 | "syscall" 19 | "time" 20 | "unsafe" 21 | ) 22 | 23 | type tmebuf struct { 24 | id C.ENDPOINT_ID 25 | pid uint64 26 | iptype int 27 | ip []byte 28 | port []byte 29 | buf []byte 30 | options C.PNF_UDP_OPTIONS 31 | len int 32 | } 33 | 34 | var ch = make(chan tmebuf, 5000) 35 | 36 | //发送函数 37 | func SendTo(id C.ENDPOINT_ID, pid uint64, iptype int, ip []byte, port []byte, buf []byte, opt C.PNF_UDP_OPTIONS, l int) { 38 | 39 | ch <- tmebuf{id: id, pid: pid, iptype: iptype, ip: ip, port: port, buf: buf, options: opt, len: l} 40 | 41 | } 42 | 43 | // Udp 本地监听转发 44 | func udpLocal(localaddr string, ctx context.Context) { 45 | 46 | //udp超时 47 | var nm = newNATmap(5 * time.Minute) 48 | var pBuf tmebuf 49 | 50 | for { 51 | 52 | select { 53 | case <-ctx.Done(): //关闭信号 54 | return 55 | 56 | case pBuf = <-ch: //数据处理 57 | 58 | //查找进程对应的代理信息 59 | prs, ok := proxyMap.Load(pBuf.pid) 60 | if !ok { 61 | continue 62 | } 63 | ProcessProxy, ok := prs.(ProxyInfo) 64 | if !ok { 65 | continue 66 | } 67 | 68 | key := string(pBuf.id) 69 | 70 | switch ProcessProxy.ptype { 71 | 72 | case AtypSocks5: //Socks5 73 | 74 | //查找驱动ID对应的Socks5握手端口 75 | Socks, ok := ProcessProxy.socks.Get(int64(pBuf.id)) 76 | if ok != true { 77 | continue 78 | } 79 | 80 | //Socks5的发送地址为空则丢弃该包 81 | if Socks.server == nil { 82 | continue 83 | } 84 | 85 | //在UDP NAT 中查找记录 86 | pc := nm.Get(key) 87 | 88 | if pc == nil { 89 | var err error 90 | pc, err = net.ListenPacket("udp", localaddr) 91 | if err != nil { 92 | continue 93 | } 94 | //NAT 添加记录 95 | nm.Add(key, tmebuf{id: pBuf.id, pid: pBuf.pid, options: pBuf.options}, pc, AtypSocks5, ProcessProxy.socks) 96 | } 97 | 98 | //发送UDP请求 99 | buf := UDPByte(pBuf.iptype, pBuf.ip, pBuf.port, pBuf.buf, pBuf.len, AtypSocks5) 100 | if buf == nil { 101 | continue 102 | } 103 | n, err := pc.WriteTo(buf, Socks.server) 104 | if err != nil { 105 | continue 106 | } 107 | 108 | mcc <- mccInfo{pid: pBuf.pid, to: AtypSend, bytebyte: int64(n)} 109 | 110 | case AtypShadowSocks: //Shadowsocks 111 | 112 | pc := nm.Get(key) 113 | if pc == nil { 114 | var err error 115 | pc, err = net.ListenPacket("udp", localaddr) 116 | if err != nil { 117 | continue 118 | } 119 | pc = ProcessProxy.ciph.PacketConn(pc) 120 | //NAT 添加记录 121 | nm.Add(key, tmebuf{id: pBuf.id, options: pBuf.options, pid: pBuf.pid}, pc, AtypShadowSocks, nil) 122 | } 123 | 124 | //发送UDP请求 125 | buf := UDPByte(pBuf.iptype, pBuf.ip, pBuf.port, pBuf.buf, pBuf.len, AtypShadowSocks) 126 | if buf == nil { 127 | continue 128 | } 129 | 130 | n, err := pc.WriteTo(buf, ProcessProxy.ssAddr) 131 | if err != nil { 132 | continue 133 | } 134 | mcc <- mccInfo{pid: pBuf.pid, to: AtypSend, bytebyte: int64(n)} 135 | 136 | default: 137 | continue 138 | } 139 | } 140 | 141 | } 142 | } 143 | 144 | // Packet NAT table 145 | type natmap struct { 146 | sync.RWMutex 147 | m map[string]net.PacketConn 148 | timeout time.Duration 149 | } 150 | 151 | func newNATmap(timeout time.Duration) *natmap { 152 | m := &natmap{} 153 | m.m = make(map[string]net.PacketConn) 154 | m.timeout = timeout 155 | return m 156 | } 157 | 158 | func (m *natmap) Get(key string) net.PacketConn { 159 | m.RLock() 160 | defer m.RUnlock() 161 | return m.m[key] 162 | } 163 | 164 | func (m *natmap) Set(key string, pc net.PacketConn) { 165 | m.Lock() 166 | defer m.Unlock() 167 | 168 | m.m[key] = pc 169 | } 170 | 171 | func (m *natmap) Del(key string) { 172 | m.Lock() 173 | defer m.Unlock() 174 | 175 | if pc, ok := m.m[key]; ok { 176 | pc.Close() 177 | delete(m.m, key) 178 | } 179 | } 180 | 181 | func (m *natmap) Add(peer string, dst tmebuf, src net.PacketConn, info int, suP *suMap) { 182 | m.Set(peer, src) 183 | 184 | go func() { 185 | //Copy 把代理返回的数据拷贝到驱动上 186 | timedCopy(dst, src, m.timeout, info) 187 | 188 | m.Del(peer) 189 | //关闭socks5 握手连接 190 | if suP != nil { 191 | suP.Del(int64(dst.id)) 192 | } 193 | }() 194 | 195 | } 196 | 197 | // 使用读取超时将src复制到目标上的dst 198 | func timedCopy(dst tmebuf, src net.PacketConn, timeout time.Duration, info int) error { 199 | buf := make([]byte, udpBufSize) 200 | 201 | switch info { 202 | 203 | case AtypSocks5: //Socks5 204 | for { 205 | src.SetReadDeadline(time.Now().Add(timeout)) 206 | n, _, err := src.ReadFrom(buf) 207 | if err != nil { 208 | return err 209 | } 210 | 211 | if buf[3] == AtypIPv4 { 212 | 213 | var temaddr syscall.SockaddrInet4 214 | C.memcpy(unsafe.Pointer(&temaddr.Addr), unsafe.Pointer(&buf[4]), 4) 215 | p := [2]byte{buf[1+net.IPv4len+3], buf[1+net.IPv4len+1+3]} 216 | C.memcpy(unsafe.Pointer(&temaddr.Port), unsafe.Pointer(&p[0]), 4) 217 | 218 | C.nf_udpPostReceive(dst.id, (*C.uchar)(unsafe.Pointer(&temaddr)), (*C.char)(unsafe.Pointer(&buf[10])), C.int(n-10), dst.options) 219 | mcc <- mccInfo{pid: dst.pid, to: AtypRecv, bytebyte: int64(n)} 220 | continue 221 | 222 | } else { 223 | 224 | var temaddr syscall.SockaddrInet6 225 | C.memcpy(unsafe.Pointer(&temaddr.Addr), unsafe.Pointer(&buf[4]), 16) 226 | p := [2]byte{buf[1+net.IPv6len+3], buf[1+net.IPv6len+1+3]} 227 | C.memcpy(unsafe.Pointer(&temaddr.Port), unsafe.Pointer(&p[0]), 4) 228 | 229 | C.nf_udpPostReceive(dst.id, (*C.uchar)(unsafe.Pointer(&temaddr)), (*C.char)(unsafe.Pointer(&buf[22])), C.int(n-22), dst.options) 230 | mcc <- mccInfo{pid: dst.pid, to: AtypRecv, bytebyte: int64(n)} 231 | continue 232 | 233 | } 234 | } 235 | 236 | case AtypShadowSocks: //Shadowsocks 237 | for { 238 | src.SetReadDeadline(time.Now().Add(timeout)) 239 | n, _, err := src.ReadFrom(buf) 240 | if err != nil { 241 | return err 242 | } 243 | 244 | if buf[0] == AtypIPv4 { 245 | 246 | var temaddr syscall.SockaddrInet4 247 | C.memcpy(unsafe.Pointer(&temaddr.Addr), unsafe.Pointer(&buf[1]), 4) 248 | p := [2]byte{buf[1+net.IPv4len], buf[1+net.IPv4len+1]} 249 | C.memcpy(unsafe.Pointer(&temaddr.Port), unsafe.Pointer(&p[0]), 4) 250 | 251 | C.nf_udpPostReceive(dst.id, (*C.uchar)(unsafe.Pointer(&temaddr)), (*C.char)(unsafe.Pointer(&buf[7])), C.int(n-7), dst.options) 252 | mcc <- mccInfo{pid: dst.pid, to: AtypRecv, bytebyte: int64(n)} 253 | continue 254 | 255 | } else { 256 | 257 | var temaddr syscall.SockaddrInet6 258 | C.memcpy(unsafe.Pointer(&temaddr.Addr), unsafe.Pointer(&buf[1]), 16) 259 | p := [2]byte{buf[1+net.IPv6len], buf[1+net.IPv6len+1]} 260 | C.memcpy(unsafe.Pointer(&temaddr.Port), unsafe.Pointer(&p[0]), 4) 261 | 262 | C.nf_udpPostReceive(dst.id, (*C.uchar)(unsafe.Pointer(&temaddr)), (*C.char)(unsafe.Pointer(&buf[19])), C.int(n-19), dst.options) 263 | mcc <- mccInfo{pid: dst.pid, to: AtypRecv, bytebyte: int64(n)} 264 | continue 265 | 266 | } 267 | } 268 | 269 | default: 270 | return fmt.Errorf("err") 271 | } 272 | 273 | } 274 | --------------------------------------------------------------------------------