Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@ jobs:
with:
name: logs_http_go${{ matrix.go }}_${{ github.run_id }}
path: integration/logs_http
- name: Run HTTP/3 test
working-directory: integration
run: |
make http3test
make target=logs_http3 copylogs
- name: Save HTTP/3 test logs as artifact
uses: actions/upload-artifact@v4
with:
name: logs_http3_go${{ matrix.go }}_${{ github.run_id }}
path: integration/logs_http3
19 changes: 11 additions & 8 deletions integration/Makefile
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
.PHONY: all build client docker-build server proxy pingtest httptest
.PHONY: all build endpoints docker-build proxy pingtest httptest http3test

build: proxy server client docker-build cleanup
build: proxy endpoints docker-build cleanup

proxy:
GOOS=linux go build -o proxy/proxy ./proxy

server:
endpoints:
openssl req -new -x509 -newkey Ed25519 -keyout server/key.pem -out server/cert.pem -days 365 -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=server" -nodes
GOOS=linux go build -o server/server ./server

client:
GOOS=linux go build -o client/client ./client

docker-build:
openssl genpkey -algorithm Ed25519 -out proxy/key.pem
openssl req -new -x509 -key proxy/key.pem -out proxy/cert.pem -days 365 -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=example.com"
docker compose build
openssl req -new -x509 -newkey Ed25519 -keyout proxy/key.pem -out proxy/cert.pem -days 365 -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=proxy" -nodes
TESTCASE=build docker compose build

cleanup:
rm client/client || true
rm server/server || true
rm proxy/proxy || true
rm server/key.pem server/cert.pem || true
rm proxy/key.pem proxy/cert.pem || true

pingtest:
Expand All @@ -28,6 +27,9 @@ pingtest:
httptest:
TESTCASE=http docker compose up --exit-code-from client

http3test:
TESTCASE=http3 docker compose up --exit-code-from client

copylogs:
mkdir -p $(target)
docker compose logs > $(target)/docker-compose.log
Expand All @@ -36,3 +38,4 @@ copylogs:
docker cp server:/server.pcap $(target)/
docker cp proxy:/proxy_eth0.pcap $(target)/
docker cp proxy:/proxy_eth1.pcap $(target)/

34 changes: 25 additions & 9 deletions integration/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net"
"net/http"
"net/netip"
"net/url"
"os"
"os/exec"
"syscall"
Expand All @@ -25,14 +24,10 @@ import (

func main() {
proxyAddr := netip.MustParseAddrPort(os.Getenv("PROXY_ADDR"))
serverURL, err := url.Parse(os.Getenv("SERVER_ADDR"))
serverAddr, err := netip.ParseAddr(os.Getenv("SERVER_ADDR"))
if err != nil {
log.Fatalf("failed to parse server URL: %v", err)
}
serverAddr, err := netip.ParseAddrPort(serverURL.Host)
if err != nil {
log.Fatalf("failed to parse server host: %v", err)
}

keyLog, err := os.Create("keys.txt")
if err != nil {
Expand All @@ -53,13 +48,28 @@ func main() {

switch os.Getenv("TESTCASE") {
case "ping":
if err := runPingTest(serverAddr.Addr()); err != nil {
if err := runPingTest(serverAddr); err != nil {
log.Fatalf("ping test failed: %v", err)
}
case "http":
if err := runHTTPTest(serverURL.String()); err != nil {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
if err := runHTTPTest(tr, fmt.Sprintf("http://%s/hello", serverAddr)); err != nil {
log.Fatalf("HTTP test failed: %v", err)
}
case "http3":
tr := &http3.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
QUICConfig: &quic.Config{
InitialPacketSize: 1200,
EnableDatagrams: true,
},
}
defer tr.Close()
if err := runHTTPTest(tr, fmt.Sprintf("https://%s/hello", serverAddr)); err != nil {
log.Fatalf("HTTP/3 test failed: %v", err)
}
default:
log.Fatalf("unknown testcase: %s", os.Getenv("TESTCASE"))
}
Expand Down Expand Up @@ -92,7 +102,10 @@ func establishConn(proxyAddr netip.AddrPort, keyLog io.Writer) (*water.Interface
NextProtos: []string{http3.NextProtoH3},
KeyLogWriter: keyLog,
},
&quic.Config{EnableDatagrams: true, KeepAlivePeriod: 10 * time.Second},
&quic.Config{
EnableDatagrams: true,
InitialPacketSize: 1350,
},
)
if err != nil {
return nil, nil, fmt.Errorf("failed to dial QUIC connection: %w", err)
Expand Down Expand Up @@ -130,6 +143,9 @@ func establishConn(proxyAddr netip.AddrPort, keyLog io.Writer) (*water.Interface
if err != nil {
return nil, nil, fmt.Errorf("failed to get TUN interface: %w", err)
}
if err := netlink.LinkSetMTU(link, 1280); err != nil {
return nil, nil, fmt.Errorf("failed to set MTU: %w", err)
}
for _, prefix := range localPrefixes {
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: prefixToIPNet(prefix)}); err != nil {
return nil, nil, fmt.Errorf("failed to add address assigned by peer %s: %w", prefix, err)
Expand Down
5 changes: 3 additions & 2 deletions integration/client/testcases.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ func ping(dst netip.Addr, interval time.Duration, count int) (transmitted, recei
return
}

func runHTTPTest(url string) error {
resp, err := http.Get(url)
func runHTTPTest(rt http.RoundTripper, url string) error {
client := &http.Client{Transport: rt}
resp, err := client.Get(url)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions integration/client/testcases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ func TestHTTPServer(t *testing.T) {
time.Sleep(100 * time.Millisecond) // give the server a moment to start

baseURL := fmt.Sprintf("http://127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port)
require.NoError(t, runHTTPTest(baseURL+"/hello"))
require.Error(t, runHTTPTest(baseURL+"/not-hello"))
require.NoError(t, runHTTPTest(http.DefaultTransport, baseURL+"/hello"))
require.Error(t, runHTTPTest(http.DefaultTransport, baseURL+"/not-hello"))
}
2 changes: 1 addition & 1 deletion integration/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ services:
- TESTCASE=$TESTCASE
- QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING=true
- PROXY_ADDR=194.166.0.2:443
- SERVER_ADDR=http://194.166.100.3:80/hello
- SERVER_ADDR=194.166.100.3
networks:
clientnet:
ipv4_address: 194.166.0.3
Expand Down
5 changes: 1 addition & 4 deletions integration/proxy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ FROM ubuntu:24.04
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y tcpdump iputils-ping iproute2 iptables ethtool tcpdump

COPY proxy /proxy
COPY cert.pem /cert.pem
COPY key.pem /key.pem
COPY run.sh /run.sh
COPY proxy cert.pem key.pem run.sh /

RUN chmod +x /run.sh

Expand Down
3 changes: 1 addition & 2 deletions integration/server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ FROM ubuntu:24.04
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y tcpdump iputils-ping iproute2 iptables ethtool tcpdump

COPY run.sh /run.sh
COPY server /server
COPY run.sh cert.pem key.pem server /

RUN chmod +x /run.sh

Expand Down
21 changes: 18 additions & 3 deletions integration/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,32 @@ import (
"log"
"net/http"
"os"

"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
)

func main() {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!\n")
})

srv := &http.Server{Addr: ":80"}
go func() {
if err := http.ListenAndServe(":80", nil); err != nil {
log.Printf("HTTP server failed: %v\n", err)
os.Exit(1)
}
}()

if err := srv.ListenAndServe(); err != nil {
log.Printf("Server failed: %v\n", err)
server := http3.Server{
Addr: ":443",
QUICConfig: &quic.Config{
InitialPacketSize: 1200,
EnableDatagrams: true,
},
}
if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil {
log.Printf("HTTP/3 server failed: %v\n", err)
os.Exit(1)
}
}