-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Yutaro Hayakawa <yhayakawa3720@gmail.com>
- Loading branch information
1 parent
2a00f70
commit 9cc3144
Showing
5 changed files
with
288 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,9 @@ | ||
FROM debian:stretch-slim | ||
|
||
RUN apt-get update | ||
RUN apt-get install -y gcc iproute2 iptables | ||
|
||
ADD tproxy.c /tmp | ||
RUN gcc -o /usr/local/bin/tproxy /tmp/tproxy.c | ||
|
||
CMD tproxy |
This file contains 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 @@ | ||
# Simple TPROXY example | ||
|
||
![](./topo.png) | ||
|
||
This example demonstrates the basic cocept of TPROXY (a.k.a. transparent proxy). The very simple proxy server (tproxy.c) transparently intercepts the HTTP traffic between C0 and C1 and dumps the request/response to stdout. | ||
|
||
Build `tproxy:latest` docker image | ||
|
||
``` | ||
tinet build | sudo bash | ||
``` | ||
|
||
Run demo | ||
|
||
``` | ||
tinet test | sudo bash | ||
``` |
This file contains 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,84 @@ | ||
nodes: | ||
- name: C0 | ||
image: nicolaka/netshoot | ||
interfaces: | ||
- name: net0 | ||
type: direct | ||
args: R0#net0 | ||
- name: R0 | ||
image: tproxy:latest | ||
buildfile: Dockerfile | ||
buildcontext: . | ||
interfaces: | ||
- name: net0 | ||
type: direct | ||
args: C0#net0 | ||
- name: net1 | ||
type: direct | ||
args: R1#net1 | ||
- name: R1 | ||
image: nicolaka/netshoot | ||
interfaces: | ||
- name: net0 | ||
type: direct | ||
args: C1#net0 | ||
- name: net1 | ||
type: direct | ||
args: R0#net1 | ||
- name: C1 | ||
image: nicolaka/netshoot | ||
interfaces: | ||
- name: net0 | ||
type: direct | ||
args: R1#net0 | ||
node_configs: | ||
- name: C0 | ||
cmds: | ||
- cmd: ip link set net0 up | ||
- cmd: ip addr add 10.0.0.2/24 dev net0 | ||
- cmd: ip route add default via 10.0.0.1 | ||
- name: R0 | ||
cmds: | ||
- cmd: ip link set net0 up | ||
- cmd: ip link set net1 up | ||
- cmd: ip addr add 10.0.0.1/24 dev net0 | ||
- cmd: ip addr add 192.168.0.1/24 dev net1 | ||
- cmd: ip route add 10.0.1.0/24 via 192.168.0.2 | ||
- cmd: ip rule add fwmark 0x1 table 100 | ||
- cmd: ip route add local 0.0.0.0/0 dev lo table 100 | ||
- cmd: iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j MARK --set-mark 0x1 | ||
- cmd: iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --on-port 80 --tproxy-mark 0x1 | ||
- name: R1 | ||
cmds: | ||
- cmd: ip link set net0 up | ||
- cmd: ip link set net1 up | ||
- cmd: ip addr add 10.0.1.1/24 dev net0 | ||
- cmd: ip addr add 192.168.0.2/24 dev net1 | ||
- cmd: ip route add 10.0.0.0/24 via 192.168.0.1 | ||
- name: C1 | ||
cmds: | ||
- cmd: ip link set net0 up | ||
- cmd: ip addr add 10.0.1.2/24 dev net0 | ||
- cmd: ip route add default via 10.0.1.1 | ||
test: | ||
- cmds: | ||
- cmd: echo "===============================================" | ||
- cmd: echo "Starting HTTP server on C1" | ||
- cmd: echo "===============================================" | ||
- cmd: docker exec C1 python3 -m http.server 80 & | ||
- cmd: sleep 10 | ||
- cmd: echo "===============================================" | ||
- cmd: echo "curl'ing from C0 to C1" | ||
- cmd: echo "===============================================" | ||
- cmd: docker exec C0 curl -s http://10.0.1.2 | ||
- cmd: echo "===============================================" | ||
- cmd: echo "Stopping HTTP server on C1" | ||
- cmd: echo "===============================================" | ||
- cmd: docker exec C1 pkill python3 | ||
- cmd: echo "===============================================" | ||
- cmd: echo "Below shows the log of the proxy server on R0" | ||
- cmd: echo "===============================================" | ||
- cmd: docker logs R0 | ||
- cmd: echo "===============================================" | ||
- cmd: echo "You should see the proxy surely intercepts" | ||
- cmd: echo "===============================================" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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,178 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdbool.h> | ||
#include <string.h> | ||
#include <sys/types.h> | ||
#include <sys/socket.h> | ||
#include <linux/ip.h> | ||
#include <arpa/inet.h> | ||
#include <unistd.h> | ||
|
||
int | ||
create_listen_sock(struct sockaddr_in *addr) | ||
{ | ||
int error, sock; | ||
|
||
sock = socket(AF_INET, SOCK_STREAM, 0); | ||
if (sock == -1) { | ||
perror("socket"); | ||
return -1; | ||
} | ||
|
||
error = bind(sock, (struct sockaddr *)addr, sizeof(*addr)); | ||
if (error == -1) { | ||
perror("bind"); | ||
return -1; | ||
} | ||
|
||
error = setsockopt(sock, SOL_IP, IP_TRANSPARENT, &(int){1}, sizeof(int)); | ||
if (error == -1) { | ||
perror("setsockopt"); | ||
return -1; | ||
} | ||
|
||
error = listen(sock, 100); | ||
if (error == -1) { | ||
perror("listen"); | ||
return -1; | ||
} | ||
|
||
printf("listening...\n"); | ||
|
||
return sock; | ||
} | ||
|
||
#define BUF_LEN 0xffff | ||
|
||
void | ||
serve(int lsock) | ||
{ | ||
int error; | ||
|
||
while (true) { | ||
int local_sock; | ||
struct sockaddr_in local_addr; | ||
socklen_t local_len = sizeof(local_addr); | ||
|
||
local_sock = accept(lsock, (struct sockaddr *)&local_addr, &local_len); | ||
if (local_sock == -1) { | ||
perror("accept"); | ||
return; | ||
} | ||
|
||
printf("Local address %s:%u\n", inet_ntoa(local_addr.sin_addr), ntohs(local_addr.sin_port)); | ||
|
||
int remote_sock; | ||
struct sockaddr_in remote_addr; | ||
socklen_t remote_len = sizeof(remote_addr); | ||
|
||
error = getsockname(local_sock, (struct sockaddr *)&remote_addr, &remote_len); | ||
if (error == -1) { | ||
perror("getpeername"); | ||
return; | ||
} | ||
|
||
printf("Remote address %s:%u\n", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port)); | ||
|
||
remote_sock = socket(AF_INET, SOCK_STREAM, 0); | ||
if (remote_sock == -1) { | ||
perror("socket"); | ||
return; | ||
} | ||
|
||
error = setsockopt(remote_sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); | ||
if (error == -1) { | ||
perror("setsockopt"); | ||
return; | ||
} | ||
|
||
error = setsockopt(remote_sock, SOL_IP, IP_TRANSPARENT, &(int){1}, sizeof(int)); | ||
if (error == -1) { | ||
perror("setsockopt"); | ||
return; | ||
} | ||
|
||
error = bind(remote_sock, (struct sockaddr *)&local_addr, local_len); | ||
if (error == -1) { | ||
perror("bind"); | ||
return; | ||
} | ||
|
||
error = connect(remote_sock, (struct sockaddr *)&remote_addr, remote_len); | ||
if (error == -1) { | ||
perror("connect"); | ||
return; | ||
} | ||
|
||
printf("Connected to %s:%u\n", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port)); | ||
|
||
uint8_t buf[BUF_LEN]; | ||
ssize_t rlen, wlen, totlen = 0, ofs = 0; | ||
|
||
memset(buf, 0, BUF_LEN); | ||
|
||
rlen = read(local_sock, buf, BUF_LEN); | ||
if (rlen == -1) { | ||
perror("read"); | ||
return; | ||
} | ||
|
||
printf("Forwarding request\n\n%s\n", buf); | ||
|
||
wlen = write(remote_sock, buf, rlen); | ||
if (wlen == -1) { | ||
perror("write"); | ||
return; | ||
} | ||
|
||
memset(buf, 0, BUF_LEN); | ||
|
||
while (totlen < BUF_LEN) { | ||
rlen = read(remote_sock, buf + totlen, BUF_LEN - totlen); | ||
if (rlen == -1) { | ||
perror("read"); | ||
return; | ||
} else if (rlen == 0) { | ||
break; | ||
} | ||
|
||
totlen += rlen; | ||
} | ||
|
||
printf("Forwarding reply\n\n%s\n", buf); | ||
|
||
ofs = 0; | ||
while (ofs < totlen) { | ||
wlen = write(local_sock, buf + ofs, totlen - ofs); | ||
if (wlen == -1) { | ||
perror("write"); | ||
return; | ||
} | ||
|
||
ofs += wlen; | ||
} | ||
|
||
close(remote_sock); | ||
close(local_sock); | ||
} | ||
} | ||
|
||
int | ||
main(void) | ||
{ | ||
int lsock; | ||
|
||
lsock = create_listen_sock(&(struct sockaddr_in){ | ||
.sin_family = AF_INET, | ||
.sin_addr.s_addr = inet_addr("0.0.0.0"), | ||
.sin_port = htons(80), | ||
}); | ||
if (lsock == -1) { | ||
fprintf(stderr, "sock_create failed\n"); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
serve(lsock); | ||
|
||
return EXIT_SUCCESS; | ||
} |