New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
syscall: if $LD_PRELOAD is set, use connect(), execve() in libc #3744
Comments
+5e3661048f2e is the tip version now... Gentoo Linux 64bit uname -a Linux HRQ-PC 3.2.12-gentoo #16 SMP Fri Jun 8 23:08:57 CST 2012 x86_64 Intel(R) Core(TM) i3 CPU M 350 @ 2.27GHz GenuineIntel GNU/Linux panic message: panic: runtime error: index out of range goroutine 1 [running]: net.hostPortToIP(0x6f0704, 0x3, 0xf8400f6b60, 0x15, 0x0, ...) /usr/lib/go/src/pkg/net/ipsock.go:127 +0x3c8 net.ResolveTCPAddr(0x6f0704, 0x3, 0xf8400f6b60, 0x70637400000015, 0xf800000000, ...) /usr/lib/go/src/pkg/net/tcpsock.go:31 +0x51 net.resolveNetAddr(0x6fd05c, 0x6c61696400000004, 0x6f0704, 0xf800000003, 0xf8400f6b60, ...) /usr/lib/go/src/pkg/net/dial.go:50 +0x504 net.Dial(0x6f0704, 0x3, 0xf8400f6b60, 0x7ff900000015, 0x0, ...) /usr/lib/go/src/pkg/net/dial.go:92 +0x62 net/http.(*Transport).dial(0xf8400b0840, 0x6f0704, 0x70637400000003, 0xf8400f6b60, 0x15, ...) /usr/lib/go/src/pkg/net/http/transport.go:299 +0xd5 net/http.(*Transport).getConn(0xf8400b0840, 0xf8400f2420, 0xf8400f2420, 0x0, 0x0, ...) /usr/lib/go/src/pkg/net/http/transport.go:311 +0xbe net/http.(*Transport).RoundTrip(0xf8400b0840, 0xf8400b8000, 0x3b, 0x0, 0x0, ...) /usr/lib/go/src/pkg/net/http/transport.go:155 +0x2ba net/http.send(0xf8400b8000, 0xf840083030, 0xf8400b0840, 0x0, 0x0, ...) /usr/lib/go/src/pkg/net/http/client.go:133 +0x3ca net/http.(*Client).doFollowingRedirects(0x8a0a80, 0xf8400b8000, 0x0, 0x0, 0x0, ...) /usr/lib/go/src/pkg/net/http/client.go:227 +0x61c ----- stack segment boundary ----- net/http.(*Client).Get(0x8a0a80, 0xf8400f7e00, 0x7ff90000003b, 0x34, 0x0, ...) /usr/lib/go/src/pkg/net/http/client.go:176 +0xb8 net/http.Get(0xf8400f7e00, 0x7d0000003b, 0xf8400f7e00, 0x0, 0x0, ...) /usr/lib/go/src/pkg/net/http/client.go:158 +0x51 main.httpGET(0xf8400f7e00, 0xf80000003b, 0x0, 0x0, 0x0, ...) /usr/lib/go/src/cmd/go/http.go:25 +0x77 main.bitbucketVCS(0xf8400f6b00, 0xf8400f6b00, 0x7025c4, 0x6f70657200000004) /usr/lib/go/src/cmd/go/vcs.go:645 +0xce main.repoRootForImportPathStatic(0xf8400f6840, 0x7ff90000001e, 0x6ee114, 0x0, 0x400, ...) /usr/lib/go/src/cmd/go/vcs.go:388 +0x76f main.repoRootForImportPath(0xf8400f6840, 0x1e, 0x4, 0x30, 0xf840000438, ...) /usr/lib/go/src/cmd/go/vcs.go:323 +0x4e main.downloadPackage(0xf8400faa00, 0xf8400e5180, 0xf8400f6840, 0xf80000001e) /usr/lib/go/src/cmd/go/get.go:242 +0x1192 main.download(0xf8400f6840, 0x10000001e, 0x7ff9118cbdb0, 0x100000001, 0x100000000, ...) /usr/lib/go/src/cmd/go/get.go:161 +0x7ec main.runGet(0x89b660, 0xf840083020, 0x100000001, 0x0) /usr/lib/go/src/cmd/go/get.go:68 +0xc6 main.main() /usr/lib/go/src/cmd/go/main.go:141 +0x48e goroutine 2 [syscall]: created by runtime.main /usr/lib/go/src/pkg/runtime/proc.c:221 |
yes, i think proxychains4 is the root cause. part of go net library calls libc's dns lookup functions, which get intercepted by proxychains4; but other part of go use networking syscalls directly, and won't be intercepted by proxychains4. there is no easy solutions to this problem. transparent socks proxy for 'go get' is not possible, iiuc. |
$ nm libproxychains4.so 0000000000206d60 a _DYNAMIC 0000000000206fe8 a _GLOBAL_OFFSET_TABLE_ w _Jv_RegisterClasses 0000000000206d50 d __DTOR_END__ 0000000000207220 A __bss_start w __cxa_finalize@@GLIBC_2.2.5 0000000000207210 d __dso_handle U __errno_location@@GLIBC_2.2.5 w __gmon_start__ 0000000000207220 A _edata 00000000011843c8 A _end 0000000000005718 T _fini 0000000000001e28 T _init U abort@@GLIBC_2.2.5 00000000002072a0 b addr_name U atoi@@GLIBC_2.2.5 0000000000005740 r base64 00000000002092c0 b buf.5444 0000000000003819 t calc_alive 000000000000387a t chain_step U close@@GLIBC_2.2.5 0000000000005116 T connect 00000000000039c7 T connect_proxy_chain 000000000000233c T dalias_hash U dlerror@@GLIBC_2.2.5 U dlsym@@GLIBC_2.2.5 U dup2@@GLIBC_2.2.5 0000000000002579 t encode_base_64 U exit@@GLIBC_2.2.5 U fclose@@GLIBC_2.2.5 U fcntl@@GLIBC_2.2.5 U fflush@@GLIBC_2.2.5 U fgets@@GLIBC_2.2.5 U fopen@@GLIBC_2.2.5 U fprintf@@GLIBC_2.2.5 U fputs@@GLIBC_2.2.5 U free@@GLIBC_2.2.5 0000000000005481 T freeaddrinfo U fwrite@@GLIBC_2.2.5 000000000000478d t get_chain_data 00000000000053f5 T getaddrinfo U getenv@@GLIBC_2.2.5 00000000000055de T gethostbyaddr 00000000000053aa T gethostbyname U gethostent@@GLIBC_2.2.5 U gethostname@@GLIBC_2.2.5 00000000000054e3 T getnameinfo U getservbyname@@GLIBC_2.2.5 U getsockopt@@GLIBC_2.2.5 U gettimeofday@@GLIBC_2.2.5 00000000002092e0 b he.5447 0000000000207260 b hostent_space U htons@@GLIBC_2.2.5 000000000000239f T index_from_internal_ip U inet_addr@@GLIBC_2.2.5 U inet_aton@@GLIBC_2.2.5 U inet_ntop@@GLIBC_2.2.5 U inet_pton@@GLIBC_2.2.5 00000000002092b8 b init_l 00000000000044bc t init_lib 0000000000207240 B internal_ips 0000000000209360 B internal_ips_lock 0000000000209300 b ipv4.5445 0000000000209310 b list.5446 00000000000058ac r local_host 00000000011813c0 B localnet_addr 000000000000244b T make_internal_ip U malloc@@GLIBC_2.2.5 U memcpy@@GLIBC_2.14 U memset@@GLIBC_2.2.5 U ntohl@@GLIBC_2.2.5 U ntohs@@GLIBC_2.2.5 00000000002092b0 B num_localnet_addr U perror@@GLIBC_2.2.5 U poll@@GLIBC_2.2.5 0000000000002499 t poll_retry 0000000000004252 T proxy_getaddrinfo 0000000000003e91 T proxy_gethostbyname 00000000002093a0 B proxychains_ct 00000000002092a0 B proxychains_got_chain_data 0000000000207218 D proxychains_max_chain 00000000002093c0 B proxychains_pd 00000000002092ac B proxychains_proxy_count 00000000002092a4 B proxychains_quiet_mode 00000000002092a8 B proxychains_resolver 00000000000027cf T proxychains_write_log U pthread_mutex_init@@GLIBC_2.2.5 U pthread_mutex_lock@@GLIBC_2.2.5 U pthread_mutex_unlock@@GLIBC_2.2.5 U rand@@GLIBC_2.2.5 U read@@GLIBC_2.2.5 000000000000295b t read_n_bytes U realloc@@GLIBC_2.2.5 0000000000003780 t release_all 00000000000037be t release_busy 000000000020721c D remote_dns_subnet 0000000000207280 b resolved_addr 0000000000207290 b resolved_addr_p 0000000000003615 t select_proxy U send@@GLIBC_2.2.5 U snprintf@@GLIBC_2.2.5 U socket@@GLIBC_2.2.5 U srand@@GLIBC_2.2.5 U sscanf@@GLIBC_2.2.5 00000000000034e3 t start_chain U stderr@@GLIBC_2.2.5 U strcat@@GLIBC_2.2.5 U strchr@@GLIBC_2.2.5 U strcmp@@GLIBC_2.2.5 U strcpy@@GLIBC_2.2.5 00000000000023d9 T string_from_internal_ip U strlen@@GLIBC_2.2.5 U strncpy@@GLIBC_2.2.5 U strspn@@GLIBC_2.2.5 U strstr@@GLIBC_2.2.5 00000000002093a4 B tcp_connect_time_out 00000000011843c0 B tcp_read_time_out U time@@GLIBC_2.2.5 00000000000029f9 t timed_connect 0000000000209340 B true_connect 0000000000209330 B true_freeaddrinfo 0000000000209320 B true_getaddrinfo 0000000000209338 B true_gethostbyaddr 0000000000209348 B true_gethostbyname 0000000000209328 B true_getnameinfo 0000000000002aff t tunnel_to U vsprintf@@GLIBC_2.2.5 U write@@GLIBC_2.2.5 00000000000028ec t write_n_bytes |
From https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/3ZmHFXqiUA0: maybe we need to also use execve from libc if LD_PRELOAD is set. |
one complexity of this issue: syscall package couldn't rely on cgo (or there will be circular dependencies between cmd/cgo and syscall). of course, we can use the same bootstrap mechanism for cmd/go to solve this problem, but i'd rather not to complicate the build mechanism for such small feature. any suggestions? could we move the connect hook to the net package? but then, what about the execve hook? |
i come up with a simple solution: we make runtime/cgo pulls in connect and execve from libc (only on unix) privately, and call it conditionally using 6c code in syscall. if cgo is available, then runtime/cgo will always be there, so this will work whenever possible. what do you think, Russ? |
please take a look at https://golang.org/cl/11010043/ the preliminary version that implements my idea. |
CL 11010043 is finished and ready for test and review. for transparent socks proxy to work, it must support nonblocking sockets. (for example, tsocks 1.8 doesn't, so it has to be patched with the little patch below: --- tsocks-1.8/tsocks.c 2002-07-16 06:50:52.000000000 +0800 +++ tsocks-1.8-hacked/tsocks.c 2013-07-09 06:01:36.540725793 +0800 @@ -326,8 +326,13 @@ errno = ECONNREFUSED; return(-1); } else { + int old_flag = fcntl(__fd, F_GETFL); + if(old_flag & O_NONBLOCK) + fcntl(__fd, F_SETFL, old_flag & ~O_NONBLOCK); /* Now we call the main function to handle the connect. */ rc = handle_request(newconn); + if(old_flag & O_NONBLOCK) + fcntl(__fd, F_SETFL, old_flag); /* If the request completed immediately it mustn't have been * a non blocking socket, in this case we don't need to know * about this socket anymore. */ ) |
FWIW, transparent proxy can be done without using LD_PRELOAD. |
I don't think this is ever going to happen. We don't like calling into C from Go more than we have to, and have moved to minimize when we do so (e.g. we prefer our own DNS resolver when possible). I agree with the page that @ymmt2005 referenced, which says: "Using iptables is far better than LD_PRELOAD for transparent proxy." |
by hongruiqi:
The text was updated successfully, but these errors were encountered: