├── .gitignore ├── main.go ├── LICENSE ├── README.md └── telnet_client.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.log 3 | debug -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use: Telnet-2 [Host] [Port] [Optional Timeout] 3 | 4 | Timeout (in seconds) is optional, default is 10 seconds. Host and Port are required. 5 | By default, it uses the local proxy "127.0.0.1:9050" where Tor is expected to run. If Tor is not needed, change the proxy field and recompile. 6 | */ 7 | 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "strconv" 14 | "time" 15 | ) 16 | 17 | // proxy to connect to. Empty to disable. 18 | const proxyAddress = "127.0.0.1:9050" 19 | 20 | func main() { 21 | // parse the flags: Telnet-2 [Host] [Port] [Optional Timeout] 22 | if len(os.Args) < 3 { 23 | fmt.Println("Use: Telnet-2 [Host] [Port] [Optional Timeout]") 24 | return 25 | } 26 | 27 | host := os.Args[1] 28 | port, err := strconv.Atoi(os.Args[2]) 29 | if err != nil { 30 | fmt.Println("Invalid port") 31 | return 32 | } 33 | 34 | timeout := time.Second * 10 35 | if len(os.Args) > 3 { 36 | if timeout2, err := strconv.Atoi(os.Args[3]); err != nil { 37 | timeout = time.Duration(timeout2) 38 | } 39 | } 40 | 41 | // prepare the client 42 | telnetClient := NewTelnetClient(host, port, timeout, proxyAddress) 43 | telnetClient.ProcessData(os.Stdin, os.Stdout) 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telnet-2 2 | 3 | Telnet-2 has 2 features which the original telnet does not provide: 4 | 5 | 1. By default, it connects via Tor (expecting a local proxy to run at `127.0.0.1:9050`) 6 | 2. You can optionally define the connection timeout (default is 10s). 7 | 8 | Both of those features can be important when investigating high-profile targets such as servers in North Korea. Using Tor helps to conceal your identity and helps to bypass IP blocking. 9 | 10 | ## Use 11 | 12 | ``` 13 | Telnet-2 [Host] [Port] [Optional Timeout] 14 | ``` 15 | 16 | Timeout is in seconds (the default is 10 seconds). 17 | 18 | ### Tor 19 | 20 | You can find the Tor Expert Bundle in the sub-directories of https://dist.torproject.org/torbrowser/. The latest Windows version is the file `tor-win64-0.4.0.5.zip`. Extract it and start `tor.exe`, which will start the proxy listening on `127.0.0.1:9050`. 21 | 22 | With the following server and command you can see which Tor exit node IP is assigned to the current circuit: 23 | 24 | ``` 25 | Telnet-2 telehack.com 23 26 | ipaddr 27 | ``` 28 | 29 | ## Compile 30 | 31 | Download [Go](https://golang.org/dl/) and then compile the project using the command `go build`. You can compile it on Linux, Mac and Windows. 32 | 33 | ## Copyright 34 | 35 | This is free and unencumbered software released into the public domain. -------------------------------------------------------------------------------- /telnet_client.go: -------------------------------------------------------------------------------- 1 | // Fork from https://github.com/mtojek/go-telnet but heavily modified to simplify and to optionally use a proxy. 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "fmt" 7 | "io" 8 | "log" 9 | "net" 10 | "strconv" 11 | "time" 12 | 13 | "golang.org/x/net/proxy" 14 | ) 15 | 16 | const defaultBufferSize = 4096 17 | 18 | // TelnetClient represents a TCP client which is responsible for writing input data and printing response. 19 | type TelnetClient struct { 20 | destination *net.TCPAddr 21 | responseTimeout time.Duration 22 | proxy string // Proxy to use (in the form of "IP:Port"), empty to disable 23 | } 24 | 25 | // NewTelnetClient method creates new instance of TCP client. 26 | // Proxy is in the form "IP:Port" or empty to disable. 27 | func NewTelnetClient(Host string, Port int, Timeout time.Duration, Proxy string) *TelnetClient { 28 | tcpAddr := net.JoinHostPort(Host, strconv.Itoa(Port)) 29 | resolved := resolveTCPAddr(tcpAddr) 30 | 31 | return &TelnetClient{ 32 | destination: resolved, 33 | responseTimeout: Timeout, 34 | proxy: Proxy, 35 | } 36 | } 37 | 38 | func resolveTCPAddr(addr string) *net.TCPAddr { 39 | resolved, error := net.ResolveTCPAddr("tcp", addr) 40 | if nil != error { 41 | log.Fatalf("Error occured while resolving TCP address \"%v\": %v\n", addr, error) 42 | } 43 | 44 | return resolved 45 | } 46 | 47 | // ProcessData method processes data: reads from input and writes to output. 48 | func (t *TelnetClient) ProcessData(inputData io.Reader, outputData io.Writer) { 49 | var connection net.Conn 50 | var err error 51 | 52 | // optionally use the proxy, if set 53 | if t.proxy != "" { 54 | var dialSocksProxy proxy.Dialer 55 | dialSocksProxy, err = proxy.SOCKS5("tcp", t.proxy, nil, proxy.Direct) 56 | if err != nil { 57 | return 58 | } 59 | connection, err = dialSocksProxy.Dial("tcp", t.destination.String()) 60 | } else { 61 | connection, err = net.DialTCP("tcp", nil, t.destination) 62 | } 63 | 64 | if err != nil { 65 | log.Fatalf("Error occured while connecting to address \"%v\": %v\n", t.destination.String(), err) 66 | } 67 | 68 | defer connection.Close() 69 | 70 | requestDataChannel := make(chan []byte) 71 | doneChannel := make(chan bool) 72 | responseDataChannel := make(chan []byte) 73 | 74 | go t.readInputData(inputData, requestDataChannel, doneChannel) 75 | go t.readServerData(connection, responseDataChannel) 76 | 77 | var afterEOFResponseTicker = new(time.Ticker) 78 | var afterEOFMode bool 79 | var somethingRead bool 80 | 81 | for { 82 | select { 83 | case request := <-requestDataChannel: 84 | if _, error := connection.Write(request); nil != error { 85 | log.Fatalf("Error occured while writing to TCP socket: %v\n", error) 86 | } 87 | case <-doneChannel: 88 | afterEOFMode = true 89 | afterEOFResponseTicker = time.NewTicker(t.responseTimeout) 90 | case response := <-responseDataChannel: 91 | outputData.Write([]byte(fmt.Sprintf("%v", string(response)))) 92 | somethingRead = true 93 | 94 | if afterEOFMode { 95 | afterEOFResponseTicker.Stop() 96 | afterEOFResponseTicker = time.NewTicker(t.responseTimeout) 97 | } 98 | case <-afterEOFResponseTicker.C: 99 | if !somethingRead { 100 | log.Println("Nothing read. Maybe connection timeout.") 101 | } 102 | return 103 | } 104 | } 105 | } 106 | 107 | func (t *TelnetClient) readInputData(inputData io.Reader, toSent chan<- []byte, doneChannel chan<- bool) { 108 | buffer := make([]byte, defaultBufferSize) 109 | var error error 110 | var n int 111 | 112 | reader := bufio.NewReader(inputData) 113 | 114 | for nil == error { 115 | n, error = reader.Read(buffer) 116 | toSent <- buffer[:n] 117 | } 118 | 119 | t.assertEOF(error) 120 | doneChannel <- true 121 | } 122 | 123 | func (t *TelnetClient) readServerData(connection net.Conn, received chan<- []byte) { 124 | buffer := make([]byte, defaultBufferSize) 125 | var error error 126 | var n int 127 | 128 | for nil == error { 129 | n, error = connection.Read(buffer) 130 | received <- buffer[:n] 131 | } 132 | 133 | t.assertEOF(error) 134 | } 135 | 136 | func (t *TelnetClient) assertEOF(err error) { 137 | if "EOF" != err.Error() { 138 | log.Fatalf("Error occured while operating on TCP socket: %v\n", err) 139 | } 140 | } 141 | --------------------------------------------------------------------------------