Page MenuHomeVyOS Platform

load-balancing haproxy not taking into account listen-address when checking for other services on port
Open, NormalPublicBUG

Description

When trying to use a port in haproxy that is already used as container port it cannot be used even when on different listen-address
Example:

container name mail port tcp-993 {
     destination 993
     listen-address 2001:0db8::25
     source 993
 }
load-balancing haproxy service wan-993 {
    backend mail-imaps
    listen-address 192.0.2.1 {
    }
    mode tcp
    port 993
}
vyos@vyos# commit
[ load-balancing haproxy ]
TCP port "993" is used by another service
[[load-balancing haproxy]] failed
Commit failed
vyos@vyos# set container name mail port tcp-993 source 994
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# set container name mail port tcp-993 source 993
[edit]
vyos@vyos# commit
[edit]

netstat shows the container listening on the correct address.
Also it works if i remove the container port, commit the haproxy config and then add the container config. Except that this prevents the config from applying at boot, as the container config is applied before haproxy.

Details

Version
2025.10.12-0019-rolling
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

Viacheslav triaged this task as Normal priority.Oct 13 2025, 8:08 PM
Viacheslav added a project: VyOS Rolling.

After my workaround described above:

vyos@vyos# sudo netstat -tulpn | grep 993                                         
tcp        0      0 192.0.2.1:993      0.0.0.0:*               LISTEN      513
01/haproxy
tcp6       0      0 2001:0db8::25:993  :::*                    LISTEN      784
61/conmon

and then when configuring the other way around:

edit]
vyos@vyos# set load-balancing haproxy service wan-993 port 994
[edit]
vyos@vyos# commit
[edit]
vyos@vyos# set load-balancing haproxy service wan-993 port 993
[edit]
vyos@vyos# commit
[ load-balancing haproxy ]
TCP port "993" is used by another service
[[load-balancing haproxy]] failed
Commit failed
[edit]
vyos@vyos# sudo netstat -tulpn | grep 993                     
tcp6       0      0 2001:0db8::25:993  :::*                    LISTEN      784
61/conmon
tmp_address = front_config.get('address', None)

shouldn't this be listen_address instead of address on line 75?

Edit:
It works like this in my tests

# Check if bind address:port are used by another service
tmp_address = list(front_config.get('listen_address', None))[0]
tmp_port = front_config['port']
if check_port_availability(tmp_address, int(tmp_port), 'tcp') is not True and \
        not is_listen_port_bind_service(int(tmp_port), 'haproxy'):
    raise ConfigError(f'TCP port "{tmp_address}" is used by another service')

however the and not is_listen_port_bind_service(int(tmp_port), 'haproxy'): part doesn't look right to me as it doesn't take into account the address of the bind. And I am also not sure about using list(x)[0] to get the IP from the listen-address dict.

There are several errors.

  1. listen_address instead of address
  2. `listen-address could has multiple values
vyos@r14# run show conf com | match haproxy
set load-balancing haproxy backend bk01 server 192.0.2.5 address '192.0.2.5'
set load-balancing haproxy backend bk01 server 192.0.2.5 port '993'
set load-balancing haproxy service wan-993 listen-address 192.0.2.2
set load-balancing haproxy service wan-993 port '993'
[edit]
vyos@r14# 
[edit]
vyos@r14# set  load-balancing haproxy service wan-993 listen-address 192.168.122.14
[edit]
vyos@r14# commit
[ load-balancing haproxy ]
{'backend': {'bk01': {'balance': 'round-robin',
                      'mode': 'http',
                      'server': {'192.0.2.5': {'address': '192.0.2.5',
                                               'port': '993'}}}},
 'global_parameters': {'ssl_bind_ciphers': ['ecdhe-ecdsa-aes128-gcm-sha256',
                                            'ecdhe-rsa-aes128-gcm-sha256',
                                            'ecdhe-ecdsa-aes256-gcm-sha384',
                                            'ecdhe-rsa-aes256-gcm-sha384',
                                            'ecdhe-ecdsa-chacha20-poly1305',
                                            'ecdhe-rsa-chacha20-poly1305',
                                            'dhe-rsa-aes128-gcm-sha256',
                                            'dhe-rsa-aes256-gcm-sha384'],
                       'tls_version_min': '1.3'},
 'pki': {},
 'service': {'wan-993': {'listen_address': {'192.0.2.2': {},
                                            '192.168.122.14': {}},
                         'mode': 'http',
                         'port': '993'}},
 'timeout': {'check': '5', 'client': '50', 'connect': '10', 'server': '50'}}

[edit]
vyos@r14#

At first glance, something like this:

# Check if bind address:port are used by another service
tmp_addresses = front_config.get('listen_address', {})
tmp_port = front_config['port']
for address, _ in tmp_addresses.items():
    if check_port_availability(address, int(tmp_port), 'tcp') is not True and \
            not is_listen_port_bind_service(int(tmp_port), 'haproxy'):
        raise ConfigError(f'TCP port "{tmp_port}" on {address} is used by another service')

But verify cannot detect that port is already used for some reason
Though the check_port_availability looks working

vyos@r14# sudo netstat -tulpn | grep 993
tcp        0      0 192.168.122.14:993      0.0.0.0:*               LISTEN      16148/conmon        
tcp        0     16 192.0.2.2:993           0.0.0.0:*               LISTEN      16862/haproxy       
[edit]
vyos@r14# 
[edit]
vyos@r14# sudo python3
Python 3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> from vyos.utils.network import check_port_availability
>>> check_port_availability('192.168.122.14', 993)
False
>>>

however the and not is_listen_port_bind_service(int(tmp_port), 'haproxy'): part doesn't look right to me as it doesn't take into account the address of the bind.

It simply checks if we already have it in the HAProxy config, so we shouldn't fail it if our service binds it. Otherwise, it will fail each time.

ruffy91 renamed this task from Cannot reuse port for haproxy that is used as container port to load-balancing haproxy not taking into account listen-address when checking for other services on port.Oct 31 2025, 7:41 PM