加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang tcp 转发

发布时间:2020-12-16 18:26:30 所属栏目:大数据 来源:网络整理
导读:package mainimport ( "os" "io" "fmt" "net" "strings" "strconv" "syscall" "encoding/binary")type CSPair struct { clientaddr net.Addr serveraddr net.Addr clientconn *net.TCPConn serverconn *net.TCPConn}const ( SO_ORIGINAL_DST = 80)var ( conn
package main

import (
  "os"
  "io"
  "fmt"
  "net"
  "strings"
  "strconv"
  "syscall"
  "encoding/binary"
)

type CSPair struct {
  clientaddr net.Addr
  serveraddr net.Addr
  clientconn *net.TCPConn
  serverconn *net.TCPConn
}

const (
  SO_ORIGINAL_DST = 80
)

var (
  connection_count = 0
)

func main() {
  laddr := &net.TCPAddr{}
  laddr.Port = 8838
  ln,err := net.ListenTCP("tcp4",laddr)
  handle_error(err)
  fmt.Printf("listen on %dn",laddr.Port)
  defer ln.Close()

  for {
    conn,err := ln.AcceptTCP()
    handle_error(err)
    pair := construct_connection(conn)
    handle_data(pair)
  }
}

func handle_data(pair *CSPair) {
  go handle_cs(pair)
  go handle_sc(pair)
}

func handle_cs(pair *CSPair) {
  defer pair.clientconn.Close()
  if strings.Index(pair.serveraddr.String(),":843") != -1 {
    fmt.Println(":843 connection.")
    io.Copy(pair.serverconn,pair.clientconn)
    return
  }

  var remain_data []byte
  for {
    bs,err := readPacket(pair.clientconn)
    handle_error(err)
    remain_data = append(remain_data,bs...)
    packet_len := int(binary.LittleEndian.Uint32(remain_data))
    packet_len += 4 //fixed len.
    fmt.Printf("remain_data: 0x%x,packet_len: 0x%xn",len(remain_data),packet_len)
    if packet_len > len(remain_data) {
      continue
    }
    packet_data := remain_data[:packet_len]
    remain_data = remain_data[packet_len:]
    //packet_data = append(packet_data,0)
    fmt.Printf("receive 0x%x:%sn",packet_len,string(packet_data))
    n,err := pair.serverconn.Write(packet_data)
    handle_error(err)
    fmt.Printf("handle_cs write 0x%x bytesn",n)
  }
}

func handle_sc(pair *CSPair) {
  defer pair.serverconn.Close()
  io.Copy(pair.clientconn,pair.serverconn)
  fmt.Println("handle_sc close pair.serverconn")
  /*
  bs,err := readPacket(pair.serverconn)
  handle_error(err)
  fmt.Printf("handle_sc:%sn",string(bs))
  pair.clientconn.Write(bs)
  */
}

func construct_connection(c *net.TCPConn) *CSPair {
  var pair = &CSPair{}
  pair.clientconn = c
  pair.clientaddr = (*c).RemoteAddr()
  f,err := c.File()
  handle_error(err)

  addr,err := syscall.GetsockoptIPv6Mreq(int(f.Fd()),syscall.IPPROTO_IP,SO_ORIGINAL_DST)
  handle_error(err)

  ipv4 := strconv.Itoa(int(addr.Multiaddr[4])) + "." +
      strconv.Itoa(int(addr.Multiaddr[5])) + "." +
      strconv.Itoa(int(addr.Multiaddr[6])) + "." +
      strconv.Itoa(int(addr.Multiaddr[7]))

  port := uint16(addr.Multiaddr[2]) << 8 + uint16(addr.Multiaddr[3])
  origin_ipv4 := ipv4
  origin_port := port

  sa,err := net.ResolveTCPAddr("tcp4",fmt.Sprintf("%s:%d",ipv4,port))
  handle_error(err)
  pair.serveraddr = sa
  pair.serverconn,err = net.DialTCP("tcp4",nil,sa)
  handle_error(err)

  connection_count++
  fmt.Printf("accept %d,%s and create a new connection to server %s(%s:%d)n",connection_count,pair.clientaddr.String(),pair.serveraddr.String(),origin_ipv4,origin_port)
  return pair
}

func handle_error(err error) {
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读