-
Notifications
You must be signed in to change notification settings - Fork 0
RAV-2958 - Initial Proxy Protocol processing #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
e18e18d
RAV-2958 - Initial Proxy Protocol processing
bplessis-swi 887da06
add spec link
bplessis-swi a34382d
fix tls constructor
bplessis-swi b3e5389
cleanup test
bplessis-swi 74755f0
only test supported java releases
bplessis-swi b74f019
cleanup end of files spaces
bplessis-swi a4751e6
add test suite for basic cache
bplessis-swi f260ccd
update readme
bplessis-swi 5b8a9bb
Split decoder in functions
bplessis-swi 9d7cd72
Switch to external library for encoding headers in tests
bplessis-swi 50e65a2
whitespaces
bplessis-swi f4292cf
Update README.md
bplessis-swi c47fb02
Fix license file, use leshan compatible BSD-3-Clause
bplessis-swi 47e6df3
Update proxy-socket-core/src/main/java/net/airvantage/proxysocket/cor…
bplessis-swi 9029e73
Update proxy-socket-core/src/main/java/net/airvantage/proxysocket/cor…
bplessis-swi 340dde3
Update proxy-socket-core/src/main/java/net/airvantage/proxysocket/cor…
bplessis-swi eda9898
take in account simon's review
bplessis-swi b23bb8f
add serialVersionUID
bplessis-swi 4770613
remove unused
bplessis-swi 128bcac
add optional TLV parsing flag
bplessis-swi dbfe0f8
remove uneeded import
bplessis-swi 8876188
remove uneeded import
bplessis-swi b1ccf69
remove uneeded import
bplessis-swi beb2682
cleanup null test
bplessis-swi e05039f
rename variable
bplessis-swi e0902be
last cleanups
bplessis-swi 30ef605
cleanups
bplessis-swi 3098cb2
remove suggested unused imports
bplessis-swi 175c850
expand the throw to a block
bplessis-swi 77c6d8b
Take in account simon's review
bplessis-swi 236e1ab
Use java 16 records
bplessis-swi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: Pull Request | ||
| on: | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: ci-${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| build: | ||
| name: Build and Test (Java ${{ matrix.java }}) | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| java: [ '17', '21' ] | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Java | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin | ||
| java-version: ${{ matrix.java }} | ||
| cache: maven | ||
|
|
||
| - name: Build and test | ||
| run: | | ||
| mvn -B -e --fail-at-end clean verify | ||
|
|
||
| - name: Upload test reports | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: test-reports-java-${{ matrix.java }} | ||
| path: | | ||
| ./**/target/surefire-reports/** | ||
| ./**/target/failsafe-reports/** | ||
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| Copyright (c) 2025, Semtech Corporation. | ||
| All rights reserved. | ||
|
|
||
| Redistribution and use in source and binary forms, with or without modification, | ||
| are permitted provided that the following conditions are met: | ||
|
|
||
| * Redistributions of source code must retain the above copyright notice, this | ||
| list of conditions and the following disclaimer. | ||
|
|
||
| * Redistributions in binary form must reproduce the above copyright notice, this | ||
| list of conditions and the following disclaimer in the documentation and/or | ||
| other materials provided with the distribution. | ||
|
|
||
| * Neither the name of the Eclipse Foundation, Inc. nor the names of its | ||
| contributors may be used to endorse or promote products derived from | ||
| this software without specific prior written permission. | ||
|
|
||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
bplessis-swi marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,62 @@ | ||
| # proxy-socket-java | ||
| Java Library to handle ProxyProtocol v2 on standard java sockets | ||
| # Proxy Socket Java (UDP + TCP, Java 17) | ||
|
|
||
| ## Overview | ||
|
|
||
| Library providing HAProxy Proxy Protocol v2 support for UDP and TCP. Multi-module layout: | ||
|
|
||
| - proxy-socket-core: zero dependencies, parser, models, interfaces | ||
| - proxy-socket-udp: DatagramSocket wrapper | ||
| - proxy-socket-tcp: ServerSocket/Socket wrappers | ||
| - proxy-socket-guava: optional Guava-based cache | ||
| - proxy-socket-examples: runnable samples | ||
|
|
||
| Reference: [HAProxy Proxy Protocol Specifications](https://www.haproxy.org/download/3.3/doc/proxy-protocol.txt) | ||
|
|
||
| ## Quick start (UDP) | ||
|
|
||
| ```java | ||
| var socket = new net.airvantage.proxysocket.udp.ProxyDatagramSocket.Builder() | ||
| .maxEntries(10_000) | ||
| .ttl(java.time.Duration.ofMinutes(5)) | ||
| .metrics(new MyMetrics()) | ||
| .build(); | ||
| socket.bind(new java.net.InetSocketAddress(9999)); | ||
| var buf = new byte[2048]; | ||
| var packet = new java.net.DatagramPacket(buf, buf.length); | ||
| socket.receive(packet); // header stripped, source set to real client | ||
| socket.send(packet); // destination rewritten to LB if cached | ||
| ``` | ||
|
|
||
| ## Quick start (TCP) | ||
|
|
||
| ```java | ||
| try (var server = new net.airvantage.proxysocket.tcp.ProxyServerSocket(9998)) { | ||
| for (;;) { | ||
| var s = (net.airvantage.proxysocket.tcp.ProxySocket) server.accept(); | ||
| var header = s.getHeader(); | ||
| // header.getSourceAddress() is the real client address | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## License | ||
|
|
||
| MIT License © 2025 Semtech. See `LICENSE`. | ||
|
|
||
| ## Metrics hook | ||
|
|
||
| Implement `net.airvantage.proxysocket.core.ProxySocketMetricsListener` and pass it via UDP builder or TCP server ctor. | ||
|
|
||
| ## Thread safety | ||
|
|
||
| - UDP/TCP wrappers follow JDK `DatagramSocket`/`ServerSocket`/`Socket` thread-safety; caches and listeners must be thread-safe. | ||
| - Core parser is stateless and thread-safe. | ||
|
|
||
| ## Configuration | ||
|
|
||
| - UDP cache defaults: 10k entries, 5 min TTL if Guava present; otherwise concurrent map (no TTL). | ||
| - TCP: blocking header read on accept with configurable timeout. | ||
|
|
||
| ## Examples | ||
|
|
||
| See `proxy-socket-examples` module: `UdpEchoWithProxyProtocol`, `TcpEchoWithProxyProtocol`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
|
|
||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>net.airvantage</groupId> | ||
| <artifactId>proxysocket-java</artifactId> | ||
| <version>1.0.0-SNAPSHOT</version> | ||
| <packaging>pom</packaging> | ||
|
|
||
| <description>ProxyProtocol Java implementation.</description> | ||
|
|
||
| <properties> | ||
|
|
||
| <!-- Dependency versions --> | ||
| <junit.version>5.10.3</junit.version> | ||
|
|
||
| </properties> | ||
|
|
||
| <modules> | ||
| <module>proxy-socket-core</module> | ||
| </modules> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>3.11.0</version> | ||
| <configuration> | ||
| <encoding>UTF-8</encoding> | ||
| <release>17</release> | ||
| </configuration> | ||
| </plugin> | ||
|
|
||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-surefire-plugin</artifactId> | ||
| <version>3.2.5</version> | ||
| <configuration> | ||
| <useModulePath>false</useModulePath> | ||
| </configuration> | ||
| </plugin> | ||
|
|
||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-resources-plugin</artifactId> | ||
| <version>3.3.1</version> | ||
| <configuration> | ||
| <encoding>UTF-8</encoding> | ||
| </configuration> | ||
| </plugin> | ||
|
|
||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-eclipse-plugin</artifactId> | ||
| <version>2.10</version> | ||
| <configuration> | ||
| <downloadSources>true</downloadSources> | ||
| <downloadJavadocs>true</downloadJavadocs> | ||
| </configuration> | ||
| </plugin> | ||
|
|
||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-source-plugin</artifactId> | ||
| <version>3.3.0</version> | ||
| <executions> | ||
| <execution> | ||
| <id>attach-sources</id> | ||
| <goals> | ||
| <goal>jar</goal> | ||
| </goals> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
|
|
||
| </plugins> | ||
| </build> | ||
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>net.airvantage</groupId> | ||
| <artifactId>proxysocket-java</artifactId> | ||
| <version>1.0.0-SNAPSHOT</version> | ||
| </parent> | ||
| <artifactId>proxy-socket-core</artifactId> | ||
| <name>Proxy Protocol - Core</name> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <properties> | ||
| <maven.compiler.release>17</maven.compiler.release> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <!-- Core must have zero required dependencies --> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter</artifactId> | ||
| <version>${junit.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- AWS ProProt library for test validation against known encoder --> | ||
| <dependency> | ||
| <groupId>com.amazonaws.proprot</groupId> | ||
| <artifactId>proprot</artifactId> | ||
| <version>1.0</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| </project> | ||
|
|
||
|
|
17 changes: 17 additions & 0 deletions
17
proxy-socket-core/src/main/java/net/airvantage/proxysocket/core/ProxyAddressCache.java
bplessis-swi marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /** | ||
| * BSD-3-Clause License. | ||
| * Copyright (c) 2025 Semtech | ||
| */ | ||
| package net.airvantage.proxysocket.core; | ||
|
|
||
| import java.net.InetSocketAddress; | ||
|
|
||
| /** | ||
| * Thread-safe cache abstraction mapping real client addresses to proxy/load-balancer addresses. | ||
| */ | ||
| public interface ProxyAddressCache { | ||
| void put(InetSocketAddress clientAddr, InetSocketAddress proxyAddr); | ||
| InetSocketAddress get(InetSocketAddress clientAddr); | ||
| void invalidate(InetSocketAddress clientAddr); | ||
| void clear(); | ||
| } |
16 changes: 16 additions & 0 deletions
16
proxy-socket-core/src/main/java/net/airvantage/proxysocket/core/ProxyProtocolException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /** | ||
| * BSD-3-Clause License. | ||
| * Copyright (c) 2025 Semtech | ||
| */ | ||
| package net.airvantage.proxysocket.core; | ||
|
|
||
| public class ProxyProtocolException extends Exception { | ||
bplessis-swi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| private static final long serialVersionUID = 1L; | ||
|
|
||
| public ProxyProtocolException(String message) { | ||
| super(message); | ||
| } | ||
| public ProxyProtocolException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
19 changes: 19 additions & 0 deletions
19
...cket-core/src/main/java/net/airvantage/proxysocket/core/ProxyProtocolMetricsListener.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /** | ||
| * BSD-3-Clause License. | ||
| * Copyright (c) 2025 Semtech | ||
| */ | ||
| package net.airvantage.proxysocket.core; | ||
|
|
||
| import net.airvantage.proxysocket.core.v2.ProxyHeader; | ||
| import java.net.InetSocketAddress; | ||
|
|
||
| /** | ||
| * Metrics/observability callbacks for Proxy Protocol processing. | ||
| * Implementations must be thread-safe. | ||
| */ | ||
| public interface ProxyProtocolMetricsListener { | ||
| default void onHeaderParsed(ProxyHeader header) {} | ||
| default void onParseError(Exception e) {} | ||
| default void onCacheHit(InetSocketAddress client) {} | ||
| default void onCacheMiss(InetSocketAddress client) {} | ||
| } |
16 changes: 16 additions & 0 deletions
16
...ocket-core/src/main/java/net/airvantage/proxysocket/core/ProxyProtocolParseException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /** | ||
| * BSD-3-Clause License. | ||
| * Copyright (c) 2025 Semtech | ||
| */ | ||
| package net.airvantage.proxysocket.core; | ||
|
|
||
| public final class ProxyProtocolParseException extends ProxyProtocolException { | ||
bplessis-swi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| private static final long serialVersionUID = 1L; | ||
|
|
||
| public ProxyProtocolParseException(String message) { | ||
| super(message); | ||
| } | ||
| public ProxyProtocolParseException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
37 changes: 37 additions & 0 deletions
37
...e/src/main/java/net/airvantage/proxysocket/core/cache/ConcurrentMapProxyAddressCache.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /** | ||
| * BSD-3-Clause License. | ||
| * Copyright (c) 2025 Semtech | ||
| */ | ||
| package net.airvantage.proxysocket.core.cache; | ||
|
|
||
| import net.airvantage.proxysocket.core.ProxyAddressCache; | ||
| import java.net.InetSocketAddress; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ConcurrentMap; | ||
|
|
||
| /** | ||
| * Simple thread-safe cache backed by {@link ConcurrentHashMap}. | ||
| */ | ||
| public final class ConcurrentMapProxyAddressCache implements ProxyAddressCache { | ||
| private final ConcurrentMap<InetSocketAddress, InetSocketAddress> map = new ConcurrentHashMap<>(); | ||
|
|
||
| @Override | ||
| public void put(InetSocketAddress clientAddr, InetSocketAddress proxyAddr) { | ||
| map.put(clientAddr, proxyAddr); | ||
| } | ||
|
|
||
| @Override | ||
| public InetSocketAddress get(InetSocketAddress clientAddr) { | ||
| return map.get(clientAddr); | ||
| } | ||
|
|
||
| @Override | ||
| public void invalidate(InetSocketAddress clientAddr) { | ||
| map.remove(clientAddr); | ||
| } | ||
|
|
||
| @Override | ||
| public void clear() { | ||
| map.clear(); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.