envoyproxy listeners does not echo back

I wrote a simple TCP echo server and UDP echo server in Golang.

The main goal is to expose these two services behind envoyproxy.

Below the configuration I have written:

compose.yaml

services:
  envoy:
    image: envoyproxy/envoy:dev
    ports:
      - "10000:10000"
      - "9001:9001"
      - "9002:9002"
    volumes:
      - ./envoy.yaml:/etc/envoy/envoy.yaml
      - ./cds.yaml:/var/lib/envoy/cds.yaml
      - ./lds.yaml:/var/lib/envoy/lds.yaml
  echo-tcp:
    build:
      context: .
      dockerfile: Dockerfile-echo-tcp
    ports:
      - 8081:8081
    volumes:
      - .:/tmp
  echo-udp:
      build:
        context: .
        dockerfile: Dockerfile-echo-udp
      ports:
        - 8082:8082
      volumes:
        - .:/tmp

envoy.yaml

node:
  cluster: civo-envoy-cluster
  id: civo-id

dynamic_resources:
  cds_config:
    resource_api_version: V3
    path: /var/lib/envoy/cds.yaml
  lds_config:
    resource_api_version: V3
    path: /var/lib/envoy/lds.yaml

admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 10000

cds.yaml

resources:
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
  name: civo_tcp_cluster
  load_assignment:
    cluster_name: civo_tcp_cluster
    endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 0.0.0.0
                port_value: 8081
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
  name: civo_udp_cluster
  load_assignment:
    cluster_name: civo_udp_cluster
    endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 0.0.0.0
                port_value: 8082

lds.yaml


resources:
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
  name: listener_tcp
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9001
  filter_chains:
    - filters:
      - name: filter_tcp
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
          cluster: civo_tcp_cluster
          stat_prefix: civo_stat_tcp
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
  name: listener_udp
  address:
    socket_address:
      protocol: UDP
      address: 0.0.0.0
      port_value: 9002
  filter_chains:
    - filters:
      - name: filter_udp
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig
          cluster: civo_udp_cluster
          stat_prefix: civo_stat_udp
  listener_filters:
    - name: envoy.filters.udp_listener.udp_proxy
      typed_config:
        '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig
        stat_prefix: civo_stat_udp
        matcher:
          on_no_match:
            action:
              name: udp_route
              typed_config:
                '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route
                cluster: civo_udp_cluster

Dockerfile-echo-tcp

FROM golang:1.22.2 as builder

WORKDIR /opt
COPY tcp/tcp.go .
COPY tcp/go.mod .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o tcp tcp.go

FROM scratch
WORKDIR /opt
COPY --from=builder /opt/tcp .
ENTRYPOINT [ "/opt/tcp" ]
EXPOSE 8081

Dockerfile-echo-udp

FROM golang:1.22.2 as builder

WORKDIR /opt
COPY udp/udp.go .
COPY udp/go.mod .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o udp udp.go

FROM scratch
WORKDIR /opt
COPY --from=builder /opt/udp .
ENTRYPOINT [ "/opt/udp" ]
EXPOSE 8082

tcp.go

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {

    ln, err := net.Listen("tcp", ":8081")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Listen(): %sn", err)
        os.Exit(1)
    }

    for {

        conn, err := ln.Accept()
        if err != nil {
            fmt.Fprintf(os.Stderr, "Accept(): %sn", err)
            continue
        }

        reader, writer := bufio.NewReader(conn), bufio.NewWriter(conn)

        go func() {

            buffer := make([]byte, 1024)
            reader.Read(buffer)
            writer.Write(buffer)
        }()
    }
}

udp.go

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {

    addr, _ := net.ResolveUDPAddr("udp", "0.0.0.0:8082")
    ln, err := net.ListenUDP("udp", addr)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Listen(): %sn", err)
        os.Exit(1)
    }

    reader, writer := bufio.NewReader(ln), bufio.NewWriter(ln)
    buffer := make([]byte, 1024)

    for {
        reader.Read(buffer)
        writer.Write(buffer)
    }
}

envoy.logs

envoy-1     | [2024-06-07 09:51:14.035][37][debug][filter] [source/common/tcp_proxy/tcp_proxy.cc:264] [Tags: "ConnectionId":"1"] new tcp proxy session
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:401] [Tags: "ConnectionId":"1"] readDisable: disable=true disable_count=0 state=0 buffer_length=0
envoy-1     | [2024-06-07 09:51:14.035][37][debug][filter] [source/common/tcp_proxy/tcp_proxy.cc:459] [Tags: "ConnectionId":"1"] Creating connection to cluster civo_tcp_cluster
envoy-1     | [2024-06-07 09:51:14.035][37][debug][misc] [source/common/upstream/cluster_manager_impl.cc:2269] Allocating TCP conn pool
envoy-1     | [2024-06-07 09:51:14.035][37][debug][pool] [source/common/conn_pool/conn_pool_base.cc:291] trying to create new connection
envoy-1     | [2024-06-07 09:51:14.035][37][trace][pool] [source/common/conn_pool/conn_pool_base.cc:292] ConnPoolImplBase 0x25fc7fc2a280, ready_clients_.size(): 0, busy_clients_.size(): 0, connecting_clients_.size(): 0, connecting_stream_capacity_: 0, num_active_streams_: 0, pending_streams_.size(): 1 per upstream preconnect ratio: 1
envoy-1     | [2024-06-07 09:51:14.035][37][debug][pool] [source/common/conn_pool/conn_pool_base.cc:145] creating a new connection (connecting=0)
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:1017] [Tags: "ConnectionId":"2"] connecting to 0.0.0.0:8081
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:1036] [Tags: "ConnectionId":"2"] connection in progress
envoy-1     | [2024-06-07 09:51:14.035][37][trace][pool] [source/common/conn_pool/conn_pool_base.cc:131] not creating a new connection, shouldCreateNewConnection returned false.
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:469] [Tags: "ConnectionId":"1"] raising connection event 2
envoy-1     | [2024-06-07 09:51:14.035][37][trace][filter] [source/common/tcp_proxy/tcp_proxy.cc:806] [Tags: "ConnectionId":"1"] on downstream event 2, has upstream = false
envoy-1     | [2024-06-07 09:51:14.035][37][debug][conn_handler] [source/common/listener_manager/active_tcp_listener.cc:160] [Tags: "ConnectionId":"1"] new connection from 172.20.0.1:35208
envoy-1     | [2024-06-07 09:51:14.035][37][trace][misc] [source/common/network/tcp_listener_impl.cc:114] TcpListener accepted 1 new connections.
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:614] [Tags: "ConnectionId":"1"] socket event: 2
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:737] [Tags: "ConnectionId":"1"] write ready
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:614] [Tags: "ConnectionId":"2"] socket event: 3
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:737] [Tags: "ConnectionId":"2"] write ready
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:757] [Tags: "ConnectionId":"2"] delayed connect error: 111
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:276] [Tags: "ConnectionId":"2"] closing socket: 0
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:469] [Tags: "ConnectionId":"2"] raising connection event 0
envoy-1     | [2024-06-07 09:51:14.035][37][debug][pool] [source/common/conn_pool/conn_pool_base.cc:495] [Tags: "ConnectionId":"2"] client disconnected, failure reason: delayed connect error: 111
envoy-1     | [2024-06-07 09:51:14.035][37][debug][filter] [source/common/tcp_proxy/tcp_proxy.cc:459] [Tags: "ConnectionId":"1"] Creating connection to cluster civo_tcp_cluster
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:150] [Tags: "ConnectionId":"1"] closing data_to_write=0 type=1
envoy-1     | [2024-06-07 09:51:14.035][37][debug][connection] [source/common/network/connection_impl.cc:276] [Tags: "ConnectionId":"1"] closing socket: 1
envoy-1     | [2024-06-07 09:51:14.035][37][trace][connection] [source/common/network/connection_impl.cc:469] [Tags: "ConnectionId":"1"] raising connection event 1
envoy-1     | [2024-06-07 09:51:14.035][37][trace][filter] [source/common/tcp_proxy/tcp_proxy.cc:806] [Tags: "ConnectionId":"1"] on downstream event 1, has upstream = false
envoy-1     | [2024-06-07 09:51:14.035][37][trace][conn_handler] [source/common/listener_manager/active_stream_listener_base.cc:126] [Tags: "ConnectionId":"1"] tcp connection on event 1
envoy-1     | [2024-06-07 09:51:14.035][37][debug][conn_handler] [source/common/listener_manager/active_stream_listener_base.cc:136] [Tags: "ConnectionId":"1"] adding to cleanup list
envoy-1     | [2024-06-07 09:51:14.035][37][trace][main] [source/common/event/dispatcher_impl.cc:228] item added to deferred deletion list (size=1)
envoy-1     | [2024-06-07 09:51:14.035][37][trace][main] [source/common/event/dispatcher_impl.cc:228] item added to deferred deletion list (size=2)
envoy-1     | [2024-06-07 09:51:14.035][37][trace][pool] [source/common/conn_pool/conn_pool_base.cc:131] not creating a new connection, shouldCreateNewConnection returned false.
envoy-1     | [2024-06-07 09:51:14.035][37][trace][main] [source/common/event/dispatcher_impl.cc:228] item added to deferred deletion list (size=3)
envoy-1     | [2024-06-07 09:51:14.035][37][debug][pool] [source/common/conn_pool/conn_pool_base.cc:463] invoking 1 idle callback(s) - is_draining_for_deletion_=false
envoy-1     | [2024-06-07 09:51:14.035][37][trace][upstream] [source/common/upstream/cluster_manager_impl.cc:2151] Idle pool, erasing pool for host 0.0.0.0:8081
envoy-1     | [2024-06-07 09:51:14.035][37][trace][main] [source/common/event/dispatcher_impl.cc:228] item added to deferred deletion list (size=4)
envoy-1     | [2024-06-07 09:51:14.036][37][trace][main] [source/common/event/dispatcher_impl.cc:122] clearing deferred deletion list (size=4)

The connection was made with netcat with nc -4 127.0.0.1 9001
The UDP datagram was sent with netcat with echo 'Hello from netcat!' | nc -4 -u 127.0.0.1 9002 but nothing is logged

What I am doing wrong ?

I am expecting that when a TCP connection is made and I send a payload, the payload is echoed back.

Same behaviour for UDP, datagrams must be echoed back.

Gianluca

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật