Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
P
proxy-in-proxychains
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
proxy-in-proxychains
Commits
7034dd7e
Commit
7034dd7e
authored
Apr 27, 2019
by
Krzysztof Kliś
Committed by
GitHub
Apr 27, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8 from rafaelferrari0/master
Update proxy.c to support IPv6
parents
62f0b999
666a6b6e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
117 additions
and
26 deletions
+117
-26
README.md
README.md
+29
-0
proxy.c
proxy.c
+88
-26
No files found.
README.md
View file @
7034dd7e
...
...
@@ -106,3 +106,32 @@ Add the IP to static hosts list ("/etc/hosts" on Linux, "C:\Windows\System32\Dri
sudo proxy -l 80 -h 93.184.216.119 -p 80 -i "tee input.log" -o "tee output.log"
```
Point your browser to http://www.example.com and watch the contents of input.log and output.log files.
### IPv6 support
The proxy normally will accept IPv4 and IPv6 connections if your system support it.
You can even forward IPv6 clients to any legacy IPv4 service.
By using numeric IPs on -b and -h parameters, proxy will use corresponding IPv4 or IPv6 socket to listen or connect.
The option [-b bind_address] force binding on specifc socket. It must be a local interface address.
Accepting IPv6 connections and forwarding to IPv6 service: (still accepting IPv4 connections)
```
proxy -l 8080 -h fdd0:beef:c4ea:2016::1 -p 8080
```
Accepting IPv6 connections and forwarding to legacy IPv4 service: (still accepting IPv4 connections)
```
proxy -l 8080 -h 192.168.1.2 -p 8080
```
Accepting IPv4 only connections and forwarding to IPv6 service:
```
proxy -l 8080 -b 192.168.1.1 -h fdd0:beef:c4ea:2016::1 -p 8080
```
Accepting IPv4 only connections and forwarding to IPv4 service:
```
proxy -l 8080 -b 192.168.1.1 -h 192.168.1.2 -p 8080
```
proxy.c
View file @
7034dd7e
...
...
@@ -3,6 +3,7 @@
*
* Author: Krzysztof Kliś <krzysztof.klis@gmail.com>
* Fixes and improvements: Jérôme Poulin <jeromepoulin@gmail.com>
* IPv6 support: 04/2019 Rafael Ferrari <rafaelbf@hotmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
...
...
@@ -67,11 +68,12 @@
typedef
enum
{
TRUE
=
1
,
FALSE
=
0
}
bool
;
int
check_ipversion
(
char
*
address
);
int
create_socket
(
int
port
);
void
sigchld_handler
(
int
signal
);
void
sigterm_handler
(
int
signal
);
void
server_loop
();
void
handle_client
(
int
client_sock
,
struct
sockaddr_
in
client_addr
);
void
handle_client
(
int
client_sock
,
struct
sockaddr_
storage
client_addr
);
void
forward_data
(
int
source_sock
,
int
destination_sock
);
void
forward_data_ext
(
int
source_sock
,
int
destination_sock
,
char
*
cmd
);
int
create_connection
();
...
...
@@ -84,6 +86,8 @@ char *bind_addr, *remote_host, *cmd_in, *cmd_out;
bool
foreground
=
FALSE
;
bool
use_syslog
=
FALSE
;
#define BACKLOG 20 // how many pending connections queue will hold
/* Program start */
int
main
(
int
argc
,
char
*
argv
[])
{
int
local_port
;
...
...
@@ -170,36 +174,77 @@ int parse_options(int argc, char *argv[]) {
}
}
int
check_ipversion
(
char
*
address
)
{
/* Check for valid IPv4 or Iv6 string. Returns AF_INET for IPv4, AF_INET6 for IPv6 */
struct
in6_addr
bindaddr
;
if
(
inet_pton
(
AF_INET
,
address
,
&
bindaddr
)
==
1
)
{
return
AF_INET
;
}
else
{
if
(
inet_pton
(
AF_INET6
,
address
,
&
bindaddr
)
==
1
)
{
return
AF_INET6
;
}
}
return
0
;
}
/* Create server socket */
int
create_socket
(
int
port
)
{
int
server_sock
,
optval
=
1
;
struct
sockaddr_in
server_addr
;
int
validfamily
=
0
;
struct
addrinfo
hints
,
*
res
=
NULL
;
char
portstr
[
12
];
memset
(
&
hints
,
0x00
,
sizeof
(
hints
));
server_sock
=
-
1
;
hints
.
ai_flags
=
AI_NUMERICSERV
;
/* numeric service number, not resolve */
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_socktype
=
SOCK_STREAM
;
/* prepare to bind on specified numeric address */
if
(
bind_addr
!=
NULL
)
{
/* check for numeric IP to specify IPv6 or IPv4 socket */
if
(
validfamily
=
check_ipversion
(
bind_addr
))
{
hints
.
ai_family
=
validfamily
;
hints
.
ai_flags
|=
AI_NUMERICHOST
;
/* bind_addr is a valid numeric ip, skip resolve */
}
}
else
{
/* if bind_address is NULL, will bind to IPv6 wildcard */
hints
.
ai_family
=
AF_INET6
;
/* Specify IPv6 socket, also allow ipv4 clients */
hints
.
ai_flags
|=
AI_PASSIVE
;
/* Wildcard address */
}
sprintf
(
portstr
,
"%d"
,
port
);
/* Check if specified socket is valid. Try to resolve address if bind_address is a hostname */
if
(
getaddrinfo
(
bind_addr
,
portstr
,
&
hints
,
&
res
)
!=
0
)
{
return
CLIENT_RESOLVE_ERROR
;
}
if
((
server_sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
))
<
0
)
{
if
((
server_sock
=
socket
(
res
->
ai_family
,
res
->
ai_socktype
,
res
->
ai_protocol
))
<
0
)
{
return
SERVER_SOCKET_ERROR
;
}
if
(
setsockopt
(
server_sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
optval
,
sizeof
(
optval
))
<
0
)
{
return
SERVER_SETSOCKOPT_ERROR
;
}
memset
(
&
server_addr
,
0
,
sizeof
(
server_addr
));
server_addr
.
sin_family
=
AF_INET
;
server_addr
.
sin_port
=
htons
(
port
);
if
(
bind_addr
==
NULL
)
{
server_addr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
}
else
{
server_addr
.
sin_addr
.
s_addr
=
inet_addr
(
bind_addr
);
}
if
(
bind
(
server_sock
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
))
!=
0
)
{
if
(
bind
(
server_sock
,
res
->
ai_addr
,
res
->
ai_addrlen
)
==
-
1
)
{
close
(
server_sock
);
return
SERVER_BIND_ERROR
;
}
if
(
listen
(
server_sock
,
20
)
<
0
)
{
if
(
listen
(
server_sock
,
BACKLOG
)
<
0
)
{
return
SERVER_LISTEN_ERROR
;
}
if
(
res
!=
NULL
)
freeaddrinfo
(
res
);
return
server_sock
;
}
...
...
@@ -242,7 +287,7 @@ void sigterm_handler(int signal) {
/* Main server loop */
void
server_loop
()
{
struct
sockaddr_
in
client_addr
;
struct
sockaddr_
storage
client_addr
;
socklen_t
addrlen
=
sizeof
(
client_addr
);
#ifdef USE_SYSTEMD
...
...
@@ -258,14 +303,17 @@ void server_loop() {
exit
(
0
);
}
else
connections_processed
++
;
close
(
client_sock
);
}
}
/* Handle client connection */
void
handle_client
(
int
client_sock
,
struct
sockaddr_
in
client_addr
)
void
handle_client
(
int
client_sock
,
struct
sockaddr_
storage
client_addr
)
{
if
((
remote_sock
=
create_connection
())
<
0
)
{
plog
(
LOG_ERR
,
"Cannot connect to host: %m"
);
goto
cleanup
;
...
...
@@ -378,28 +426,42 @@ void forward_data_ext(int source_sock, int destination_sock, char *cmd) {
/* Create client connection */
int
create_connection
()
{
struct
sockaddr_in
server_addr
;
struct
hostent
*
server
;
struct
addrinfo
hints
,
*
res
=
NULL
;
int
sock
;
int
validfamily
=
0
;
char
portstr
[
12
];
if
((
sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
))
<
0
)
{
return
CLIENT_SOCKET_ERROR
;
memset
(
&
hints
,
0x00
,
sizeof
(
hints
));
hints
.
ai_flags
=
AI_NUMERICSERV
;
/* numeric service number, not resolve */
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_socktype
=
SOCK_STREAM
;
sprintf
(
portstr
,
"%d"
,
remote_port
);
/* check for numeric IP to specify IPv6 or IPv4 socket */
if
(
validfamily
=
check_ipversion
(
remote_host
))
{
hints
.
ai_family
=
validfamily
;
hints
.
ai_flags
|=
AI_NUMERICHOST
;
/* remote_host is a valid numeric ip, skip resolve */
}
if
((
server
=
gethostbyname
(
remote_host
))
==
NULL
)
{
/* Check if specified host is valid. Try to resolve address if remote_host is a hostname */
if
(
getaddrinfo
(
remote_host
,
portstr
,
&
hints
,
&
res
)
!=
0
)
{
errno
=
EFAULT
;
return
CLIENT_RESOLVE_ERROR
;
}
memset
(
&
server_addr
,
0
,
sizeof
(
server_addr
));
server_addr
.
sin_family
=
AF_INET
;
memcpy
(
&
server_addr
.
sin_addr
.
s_addr
,
server
->
h_addr
,
server
->
h_length
);
server_addr
.
sin_port
=
htons
(
remote_port
);
if
((
sock
=
socket
(
res
->
ai_family
,
res
->
ai_socktype
,
res
->
ai_protocol
))
<
0
)
{
return
CLIENT_SOCKET_ERROR
;
}
if
(
connect
(
sock
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
)
)
<
0
)
{
if
(
connect
(
sock
,
res
->
ai_addr
,
res
->
ai_addrlen
)
<
0
)
{
return
CLIENT_CONNECT_ERROR
;
}
if
(
res
!=
NULL
)
freeaddrinfo
(
res
);
return
sock
;
}
/* vim: set et ts=4 sw=4: */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment