Score:0

Create UDP forwarders imitating multiple network elements that use the same port

de flag

Given:

  • I have a containerized service that sends UDP packets to a list of network elements (3rd party syslog sink servers).
  • Each target network element is specified by IP address, its port number is constant, the same for each node.

I need to create a simple test environment - like in the graph below. The main service emits syslog messages, on the graph it's named PRODUCER CONTAINER.

TEST CONTAINER can easily spawn docker containers, so I picked spawning alpine/socat:latest.

The question is:

  1. What arguments do I have to pass to socat in order to obtain the setup working?
  2. What else do I need to care about?

I tried many combinations of socat args so far, but with no luck. With socat UDP-RECV:514 UDP-SENDTO:172.25.0.2:65354,bind=:1234 I receive messages in the proxy containers, but nothing is received in the test container.

Seems that I lack of overall knowledge. Could anyone explain how it is supposed to be done?

test_environment

The code I use in the test container looks more-less like that:

import os
import platform
import threading
from socket import socket

import docker
from docker import DockerClient
from docker.models.containers import Container
from docker.models.networks import Network


def create_proxy():
    docker_client: DockerClient = docker.from_env()
    test_network: Network = docker_client.networks.create(f'test_network_{os.environ.get("HOSTNAME")}')
    testrunner_container: Container = docker_client.containers.get(platform.node())

    testrunner_container.reload()
    test_container_ip = testrunner_container.attrs['NetworkSettings']['Networks'][test_network.name]['IPAddress']

    socket_ = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    socket_.bind(('', 0))  # bind to random local port
    _, test_container_port = socket_.getsockname()
    proxy_port = 1234
    socat_args = [
        '-d', '-d', f'UDP-RECV:514', f'UDP-SENDTO:{test_container_ip}:{test_container_port},bind=:{proxy_port}',
    ]

    proxy_container: Container = docker_client.containers.run(
        'alpine/socat:latest',
        socat_args,
        name='udp_proxy_container',
        network=test_network.name,
        detach=True,
        remove=True,
    )
    proxy_container.reload()
    proxy_ip = proxy_container.attrs['NetworkSettings']['Networks'][test_network.name]['IPAddress']

    socket_ = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    socket_.bind(('', 0))  # bind to random local port

    socket_.connect((proxy_ip, proxy_port))
    socket_.settimeout(1)

    def receive_loop(queue):
        while True:
            try:
                message = socket_.recv(1024)
                if b'STOP IT' in message:
                    break
                queue.append(message)
            except socket.timeout as e:
                log.error(f"{type(e).__name__} in Syslog stub's receive loop: {e}")

    msg_queue = []
    receive_thread = threading.Thread(target=receive_loop, args=(msg_queue,))
    receive_thread.daemon = True
    receive_thread.start()

    # ... some other code

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.