[ https://issues.apache.org/jira/browse/ARTEMIS-3915?focusedWorklogId=984223&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-984223 ]
ASF GitHub Bot logged work on ARTEMIS-3915: ------------------------------------------- Author: ASF GitHub Bot Created on: 23/Sep/25 21:34 Start Date: 23/Sep/25 21:34 Worklog Time Spent: 10m Work Description: jbertram commented on code in PR #5908: URL: https://github.com/apache/activemq-artemis/pull/5908#discussion_r2373509103 ########## tests/e2e-tests/src/test/java/org/apache/activemq/artemis/tests/e2e/proxy_protocol/HAProxyTest.java: ########## @@ -0,0 +1,334 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.tests.e2e.proxy_protocol; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueRequestor; +import javax.jms.QueueSession; +import javax.jms.Session; +import java.lang.invoke.MethodHandles; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.activemq.ActiveMQSslConnectionFactory; +import org.apache.activemq.artemis.api.core.ActiveMQConnectionTimedOutException; +import org.apache.activemq.artemis.api.core.JsonUtil; +import org.apache.activemq.artemis.api.core.management.ResourceNames; +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper; +import org.apache.activemq.artemis.core.management.impl.view.predicate.ActiveMQFilterPredicate; +import org.apache.activemq.artemis.jms.client.ActiveMQQueueConnectionFactory; +import org.apache.activemq.artemis.json.JsonArray; +import org.apache.activemq.artemis.json.JsonObject; +import org.apache.activemq.artemis.tests.e2e.common.ContainerService; +import org.apache.activemq.artemis.tests.e2e.common.E2ETestBase; +import org.apache.activemq.artemis.tests.e2e.common.ValidateContainer; +import org.apache.activemq.artemis.utils.RandomUtil; +import org.apache.activemq.artemis.utils.Wait; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.eclipse.paho.mqttv5.client.IMqttToken; +import org.eclipse.paho.mqttv5.client.MqttCallback; +import org.eclipse.paho.mqttv5.client.MqttClient; +import org.eclipse.paho.mqttv5.client.MqttConnectionOptions; +import org.eclipse.paho.mqttv5.client.MqttDisconnectResponse; +import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence; +import org.eclipse.paho.mqttv5.common.MqttException; +import org.eclipse.paho.mqttv5.common.MqttMessage; +import org.eclipse.paho.mqttv5.common.packet.MqttProperties; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * You need to build the Artemis Docker image with 'mvn install -De2e-tests.skipImageBuild=false' before this test is + * executed. + */ +public class HAProxyTest extends E2ETestBase { + + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + // see haproxy.cfg + private static final int PROXY_PORT_V1 = 51617; + private static final int PROXY_PORT_V2 = 51627; + private static final int PROXY_PORT_SSL = 51618; + private static final int PROXY_PORT_INVALID = 51616; + + private static final int BROKER_PROXY_PORT = 61617; + private static final int BROKER_PROXY_SSL_PORT = 61618; + private static final int BROKER_STANDARD_PORT = 61616; + + public static final String USER_PASS = "artemis"; + public static final String PROXY_PROTOCOL_VERSION_1 = "V1"; + public static final String PROXY_PROTOCOL_VERSION_2 = "V2"; + + static Object network; + static Object haProxy; + static Object artemisServer; + + static ContainerService service = ContainerService.getService(); + + @BeforeEach + public void disableThreadcheck() { + disableCheckThread(); + } + + private static final String HAPROXY_HOME = basedir + "/target/proxy-protocol"; + + @BeforeAll + public static void startServers() throws Exception { + ValidateContainer.assumeArtemisContainer(); + + assertNotNull(basedir); + + network = service.newNetwork(); + + artemisServer = service.newBrokerImage(); + service.setNetwork(artemisServer, network); + service.exposePorts(artemisServer, BROKER_PROXY_PORT, BROKER_PROXY_SSL_PORT, BROKER_STANDARD_PORT); + service.exposeHosts(artemisServer, "broker"); + service.prepareInstance(HAPROXY_HOME); + service.exposeBrokerHome(artemisServer, HAPROXY_HOME); + service.startLogging(artemisServer, "ArtemisServer:"); + + recreateBrokerDirectory(HAPROXY_HOME); + + service.start(artemisServer); + + haProxy = service.newHaProxyImage(); + service.setNetwork(haProxy, network); + service.exposePorts(haProxy, PROXY_PORT_V1, PROXY_PORT_V2, PROXY_PORT_SSL, PROXY_PORT_INVALID); + service.exposeHosts(haProxy, "haproxy"); + service.exposeFile(haProxy, basedir + "/src/main/resources/servers/proxy-protocol/haproxy.cfg", "/usr/local/etc/haproxy/haproxy.cfg"); + service.startLogging(haProxy, "haproxy:"); + service.start(haProxy); + } + + @AfterAll + public static void stopServer() { + service.stop(artemisServer); + service.stop(haProxy); + } + + /* + * a non-proxied connection shouldn't be able to connect to an acceptor using proxyEnabled=true + */ + @Test + public void testNonProxiedConnectionToProxyAcceptor() { + testFailure(artemisServer, BROKER_PROXY_PORT); + } + + /* + * a proxied connection shouldn't be able to connect to an acceptor using proxyEnabled=false + */ + @Test + public void testProxiedConnectionToNonProxyAcceptor() { + testFailure(haProxy, PROXY_PORT_INVALID); + } + + private void testFailure(Object target, int port) { + Exception e = assertThrows(JMSException.class, () -> { + testSendReceive(service.createCF(target, "CORE", port, "?callTimeout=3000"), PROXY_PROTOCOL_VERSION_1); + }); + Throwable rootCause = ExceptionUtils.getRootCause(e); + assertNotNull(rootCause); + assertTrue(rootCause instanceof ActiveMQConnectionTimedOutException); Review Comment: I've reverted the Testcontainers stuff and integrated the new embedded PROXY server implementation. I think it's much cleaner now. Issue Time Tracking ------------------- Worklog Id: (was: 984223) Time Spent: 10h (was: 9h 50m) > Support PROXY Protocol > ---------------------- > > Key: ARTEMIS-3915 > URL: https://issues.apache.org/jira/browse/ARTEMIS-3915 > Project: ActiveMQ Artemis > Issue Type: Improvement > Components: Broker > Reporter: João Santos > Assignee: Justin Bertram > Priority: Major > Labels: pull-request-available > Time Spent: 10h > Remaining Estimate: 0h > > [HAProxy|http://www.haproxy.org/] is a widely known and used TCP Load > Balancer and especially useful for an ActiveMQ Artemis clustered environment. > Although possible to functionally implement with both products current > features, Artemis does not support the PROXY protocol, which prevents it's > broker nodes from inferring the real remote client IP address when behind an > HAProxy instance. > Since Netty sockets implementation already seems to support this protocol > (discussed w/ [~jbertram] on DEV mailing list), it shouldn't be a big leap to > adding support for the protocol on Artemis acceptors, thus improving the > deployment of the use case at hand. -- This message was sent by Atlassian Jira (v8.20.10#820010) --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@activemq.apache.org For additional commands, e-mail: issues-h...@activemq.apache.org For further information, visit: https://activemq.apache.org/contact