Go로 TCP 프록시 만들기
모든 TCP 연결 중에는 통신 로그를 캡처할 수 있습니다.
이런 이미지입니다.
구성요소
TCP 연결 수락
우선은 외부로부터의 TCP 접속을 받아들이는 부분을 만듭니다.
보통 TCP 서버를 만들 때와 같습니다.
새로운 접속이 오면 handleConn 함수를 goroutine 로 실행하는 것으로 복수의 접속을 받아들여 가능하게 하고 있습니다.
handleConn 의 내용은 이 뒤에 기술해 갑니다.
type Server struct {}
func (s *Server) Start(listenAddr *net.TCPAddr) error {
lt, err := net.ListenTCP("tcp", listenAddr)
if err != nil {
return err
}
defer lt.Close()
for {
conn, err := lt.AcceptTCP()
if err != nil {
return err
}
go s.handleConn(conn)
}
}
func (s *Server) handleConn(c *net.TCPConn) {
...
}
수락 후 양방향 릴레이
클라이언트로부터 접속한 뒤는, 진짜의 서버에 접속해,
클라이언트와 서버의 통신 내용을 릴레이(양방향으로 연결)합니다.
양방향이라는 것은
의 2방향이므로, 2개의 goroutine 를 병렬시켜 실시합니다.
func (s *Server) handleConn(c *net.TCPConn) {
defer c.Close()
// 何らかの方法で本物のサーバーのアドレスを取得しておく
serverAddr := ....
// 本物のサーバーへ接続
serverConn, err := net.DialTCP("tcp", nil, serverAddr)
if err != nil {
return err
}
defer serverConn.Close()
// 双方向のリレーを作る
p := &Proxy{}
p.Start(c, serverConn)
}
// プロキシ本体
type Proxy struct{}
// プロキシの開始(双方向リレー開始)
func (p *Proxy) Start(clientConn, serverConn) error {
defer clientConn.Close()
defer serverConn.Close()
var eg errGroup.Group
eg.Go(func() error { return p.relay(&eg, clientConn, serverConn) })
eg.Go(func() error { return p.relay(&eg, serverConn, clientConn) })
// wait for stop
return eg.Wait()
}
const (
BUFFER_SIZE = 0xFFFF
)
// fromConn -> toConn へ通信内容をリレーする
func (p *Proxy) relay(eg *errGroup.Group, fromConn, toConn *net.TCPConn) error {
buff := make([]byte, BUFFER_SIZE)
for {
n, err := fromConn.Read(buff)
if err != nil {
return err
}
b := buff[:n]
// ここでログなどを取ることができる
n, err = toConn.Write(b)
if err != nil {
return err
}
}
}
요약
참고로 한 페이지
Reference
이 문제에 관하여(Go로 TCP 프록시 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/castaneai/items/cd49a0a09c3472238bc7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)