mirror of
https://code.semirocket.science/wrapsix
synced 2025-03-13 09:31:22 +02:00
Integrated wrapper into WrapSix
Fixed bug in resolver so now even normal applications accept its answers Improved configuration - now accepts arguments from command line Cleaned the code a little bit Added simple build script Written more documentation into README Chosen the licence - GNU AGPLv3
This commit is contained in:
parent
e7d8a4c1dd
commit
c894b7186c
15
LICENCE
Normal file
15
LICENCE
Normal file
@ -0,0 +1,15 @@
|
||||
WrapSix
|
||||
Copyright (C) 2008-2009 Michal Zima <xhire@tuxportal.cz>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
36
README
36
README
@ -1,21 +1,47 @@
|
||||
#####
|
||||
## WrapSix readme
|
||||
####
|
||||
# Author: Michal Zima, 2008
|
||||
# Author: Michal Zima, 2008-2009
|
||||
# E-mail: xhire@tuxportal.cz
|
||||
#####
|
||||
|
||||
== About ==
|
||||
WrapSix is a revolutionary piece of software that make possible to reach IPv4-only servers from IPv6-only networks. It stands as a wrapper of faked IPv6 addresses to real IPv4 addresses.
|
||||
WrapSix is a revolutionary piece of software that makes possible to reach IPv4-only servers from IPv6-only networks. It stands as a wrapper of faked IPv6 addresses to real IPv4 addresses.
|
||||
|
||||
== Requirements ==
|
||||
WrapSix is very simple to use. You only need:
|
||||
* GNU/Linux system
|
||||
* Ruby (I've tested version 1.8.6)
|
||||
* GNU/Linux system with IPv6 support (best with 2.6.12 or newer; tested with 2.6.11 (OK) and 2.6.17 (OK))
|
||||
* C compiler and such things (just to build binaries of course)
|
||||
* libpcap (tested with version 0.8.3)
|
||||
* Ruby (tested with version 1.8.6)
|
||||
|
||||
== Building ==
|
||||
If you satisfied all requirements, let's run build script: './build.sh'.
|
||||
|
||||
== Configuration ==
|
||||
Look at configuration file conf/wrapsix.conf.
|
||||
|
||||
In section of the DNS resolver you have to set its IPv6 address (already assigned to the network interface of the server) and IPv4 address of already existing DNS resolver.
|
||||
|
||||
In section of the wrapper you have to set some *unused* IPv6 prefix (/96) and *unused* IPv4 address that is not set anywhere. WrapSix manage them itself. If autodetection of network device fails, set it as well, e.g. to 'eth0'.
|
||||
|
||||
The IPv6 prefix can be globaly routable - it is up to you to set the firewall appropriately.
|
||||
|
||||
If you don't need debug mode, it is recommended to disable it.
|
||||
|
||||
All configuration options can be passed on as command line arguments - run './wrapsix.rb --help' for more details. Command line arguments have higher priority and override those in configuration file.
|
||||
|
||||
== Instalation ==
|
||||
WrapSix is not stable yet - it is just experimental version. So it is not supposed to be installed in system (=> there is no installation script), but you can install it by hand if you want. The best location would be in /opt/wrapsix/ I think...
|
||||
|
||||
== Running ==
|
||||
Run WrapSix with wrapsix.rb. E.g. './wrapsix.rb'. Notice: you need root privileges.
|
||||
|
||||
It is recommended to run WrapSix on its own dedicated machine.
|
||||
|
||||
== Clients ==
|
||||
On client station set some routable IPv6 address (generally from similar prefix as WrapSix has, but not the same!) and DNS server to the address that you set in WrapSix. First test the DNS resolving (with dig, ping (as it does resolving too) or whatsoever) and then try pinging such destination that doesn't have native IPv6 connectivity (e.g. 'ping6 wrapsix.tuxportal.cz' (yes, this site doesn't have IPv6 connectivity yet).
|
||||
|
||||
Note: you have to have IPv6 connectivity (native or even a tunnel is acceptable)!
|
||||
|
||||
== Getting help ==
|
||||
You can visit official WrapSix IRC channel #wrapsix on server irc.tuxportal.cz. Thank you for feedback.
|
||||
|
@ -1,11 +1,13 @@
|
||||
### Configuration of Resolver
|
||||
resolver: 1
|
||||
#resolver_ip: '::1'
|
||||
resolver_ip: '2001:470:9985:1:200:e2ff:fe7f:414'
|
||||
secondary_resolver: 10.0.0.139 # if not set => /etc/resolv.conf
|
||||
resolver: true
|
||||
resolver_ip: 'fc00:1::1'
|
||||
secondary_resolver: 10.0.0.1 # if not set => /etc/resolv.conf
|
||||
|
||||
### Configuration of Wrapper
|
||||
wrapper: 0
|
||||
wrapper: true
|
||||
wrapper_device: # if not set => automatic detection
|
||||
wrapper_ipv6_prefix: 'fc00:2::'
|
||||
wrapper_ipv4_address: 10.0.0.111
|
||||
|
||||
### Others
|
||||
debug: 1
|
||||
debug: false
|
||||
|
@ -4,7 +4,7 @@
|
||||
#> lib/resolver.rb
|
||||
#~ WrapSix Resolver
|
||||
####
|
||||
# Author: Michal Zima, 2008
|
||||
# Author: Michal Zima, 2008-2009
|
||||
# E-mail: xhire@tuxportal.cz
|
||||
#####
|
||||
|
||||
@ -20,7 +20,6 @@ class Resolver
|
||||
@resolver = UDPSocket.open Socket::AF_INET6
|
||||
begin
|
||||
@resolver.bind $config['resolver_ip'], 53
|
||||
#rescue Errno::EPERM
|
||||
rescue Errno::EACCES
|
||||
$stderr.puts "You have to run #{$0} as root!"
|
||||
exit!
|
||||
@ -28,7 +27,6 @@ class Resolver
|
||||
puts "Started DNS resolver on IPv6 address #{$config['resolver_ip']}" if @debug
|
||||
|
||||
loop do
|
||||
puts "---------- start ----------" if @debug
|
||||
# Receive and parse query
|
||||
data = @resolver.recvfrom 2048
|
||||
print "Client: " if @debug
|
||||
@ -44,16 +42,16 @@ class Resolver
|
||||
answer.opcode = query.opcode # Type of Query; copy from query
|
||||
answer.aa = 0 # Is this an authoritative response: 0 = No, 1 = Yes
|
||||
answer.rd = query.rd # Is Recursion Desired, copied from query
|
||||
answer.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes
|
||||
answer.ra = 1 # Does name server support recursion: 0 = No, 1 = Yes
|
||||
answer.rcode = 0 # Response code: 0 = No errors
|
||||
|
||||
query.each_question do |question, typeclass| # There may be multiple questions per query
|
||||
begin
|
||||
name = question.to_s # The domain name looked for in the query.
|
||||
answer.add_question name, typeclass
|
||||
puts "Looking for: #{name}" if @debug
|
||||
#record_type = typeclass.name.split("::").last # For example "A", "MX"
|
||||
puts "RR: #{typeclass}" if @debug
|
||||
#puts "RR: #{record_type}" if @debug
|
||||
|
||||
# So let's look for it :c) (in secondary resolver)
|
||||
sr = Resolv::DNS::new :nameserver => $config['secondary_resolver']
|
||||
@ -75,18 +73,43 @@ class Resolver
|
||||
print "My answer: " if @debug
|
||||
p answer if @debug
|
||||
rescue Resolv::ResolvError
|
||||
puts "Error: DNS result has no information for #{name}"
|
||||
# creating 'faked' AAAA entry
|
||||
begin
|
||||
if typeclass == Resolv::DNS::Resource::IN::AAAA
|
||||
sr = Resolv::DNS::new :nameserver => $config['secondary_resolver']
|
||||
sr_data = sr.getresource name, Resolv::DNS::Resource::IN::A
|
||||
print "Raw answer: " if @debug
|
||||
p sr_data if @debug
|
||||
|
||||
# completing the answer
|
||||
aaaa_answer = Resolv::DNS::Resource::IN::AAAA.new(ipaddr_4to6(sr_data.address))
|
||||
print "IPv4 address: " if @debug
|
||||
p sr_data.address if @debug
|
||||
p ipaddr_4to6(sr_data.address) if @debug
|
||||
ttl = 86400 # I think ttl doesn't matter ;c)
|
||||
answer.add_answer name + ".", ttl, aaaa_answer
|
||||
|
||||
print "My answer: " if @debug
|
||||
p answer if @debug
|
||||
end
|
||||
rescue Resolv::ResolvError
|
||||
puts "Error: DNS result has no information for #{name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# send the response
|
||||
@resolver.send answer.encode, 0, data[1][3], data[1][1] # msg, flags, client, port
|
||||
|
||||
puts "---------- end ----------" if @debug
|
||||
end
|
||||
end
|
||||
|
||||
def exit
|
||||
@resolver.close
|
||||
end
|
||||
|
||||
private
|
||||
def ipaddr_4to6 ip4addr
|
||||
ip4parsed = ip4addr.to_s.match(Resolv::IPv4::Regex)
|
||||
return $config['wrapper_ipv6_prefix'] + ("%02x%02x:%02x%02x" % [ ip4parsed[1], ip4parsed[2], ip4parsed[3], ip4parsed[4] ])
|
||||
end
|
||||
end
|
||||
|
@ -4,15 +4,22 @@
|
||||
#> lib/wrapper.rb
|
||||
#~ WrapSix Wrapper
|
||||
####
|
||||
# Author: Michal Zima, 2008
|
||||
# Author: Michal Zima, 2008-2009
|
||||
# E-mail: xhire@tuxportal.cz
|
||||
#####
|
||||
|
||||
class Wrapper
|
||||
def initializer
|
||||
@debug = $config['debug']
|
||||
end
|
||||
|
||||
def start
|
||||
params = "#{$config['wrapper_ipv4_address']} #{$config['wrapper_ipv6_prefix']}"
|
||||
params += " #{$config['wrapper_device']}" if $config['wrapper_device']
|
||||
unless @debug
|
||||
params += " > /dev/null"
|
||||
end
|
||||
system "wrapper/wrapper #{params}"
|
||||
end
|
||||
|
||||
def exit
|
||||
|
@ -52,24 +52,39 @@ void process_packet4(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
printf(" From: %s\n", inet_ntoa(ip->ip_src));
|
||||
printf(" To: %s\n", inet_ntoa(ip->ip_dest));
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(&ip4addr_wrapsix, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* determine protocol */
|
||||
switch (ip->proto) {
|
||||
case IPPROTO_TCP:
|
||||
printf(" Protocol: TCP\n");
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(&ip4addr_wrapsix, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
|
||||
process_tcp4(eth, ip, payload, htons(ip->pckt_len) - header_length);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
printf(" Protocol: UDP\n");
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(dev_ip, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
|
||||
process_udp4(eth, ip, payload, htons(ip->pckt_len) - header_length);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
printf(" Protocol: ICMP\n");
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(dev_ip, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
|
||||
process_icmp4(eth, ip, payload, htons(ip->pckt_len) - header_length);
|
||||
break;
|
||||
default:
|
||||
@ -117,11 +132,11 @@ void process_tcp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
|
||||
/* check if this packet is from wrapped connection */
|
||||
if (ent == NULL) {
|
||||
fprintf(stderr, "Error: data not found\n");
|
||||
printf("Error: data not found\n");
|
||||
return;
|
||||
}
|
||||
else if (memcmp(&ent->addr_to, &ip_hdr->ip_src, sizeof(struct in_addr))) {
|
||||
fprintf(stderr, "Error: data not appropriate\n");
|
||||
printf("Error: data not appropriate\n");
|
||||
printf(" Ent-to: %s\n", inet_ntoa(ent->addr_to));
|
||||
printf(" IP-from: %s\n", inet_ntoa(ip_hdr->ip_src));
|
||||
return;
|
||||
@ -280,11 +295,11 @@ void process_udp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
|
||||
/* check if this packet is from wrapped connection */
|
||||
if (ent == NULL) {
|
||||
fprintf(stderr, "Error: data not found\n");
|
||||
printf("Error: data not found\n");
|
||||
return;
|
||||
}
|
||||
else if (memcmp(&ent->addr_to, &ip_hdr->ip_src, sizeof(struct in_addr))) {
|
||||
fprintf(stderr, "Error: data not appropriate\n");
|
||||
printf("Error: data not appropriate\n");
|
||||
printf(" Ent-to: %s\n", inet_ntoa(ent->addr_to));
|
||||
printf(" IP-from: %s\n", inet_ntoa(ip_hdr->ip_src));
|
||||
return;
|
||||
@ -387,11 +402,11 @@ void process_icmp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
|
||||
/* check if this packet is from wrapped connection */
|
||||
if (ent == NULL) {
|
||||
fprintf(stderr, "Error: data not found\n");
|
||||
printf("Error: data not found\n");
|
||||
return;
|
||||
}
|
||||
else if (memcmp(&ent->addr_to, &ip_hdr->ip_src, sizeof(struct in_addr))) {
|
||||
fprintf(stderr, "Error: data not appropriate\n");
|
||||
printf("Error: data not appropriate\n");
|
||||
printf(" Ent-to: %s\n", inet_ntoa(ent->addr_to));
|
||||
printf(" IP-from: %s\n", inet_ntoa(ip_hdr->ip_src));
|
||||
return;
|
||||
|
@ -13,9 +13,13 @@ jsw_rbtree_t *stg_conn_tcp;
|
||||
jsw_rbtree_t *stg_conn_udp;
|
||||
jsw_rbtree_t *stg_conn_icmp;
|
||||
|
||||
/*
|
||||
* 1: IPv4 address
|
||||
* 2: IPv6 prefix
|
||||
* 3: ethernet device
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
|
||||
pcap_t *handle; /* packet capture handle */
|
||||
|
||||
@ -30,10 +34,20 @@ int main(int argc, char **argv)
|
||||
|
||||
/* find a capture device */
|
||||
dev = NULL;
|
||||
dev = pcap_lookupdev(errbuf);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
|
||||
exit(EXIT_FAILURE);
|
||||
printf("Args: %d\n", argc);
|
||||
if (argc == 4) {
|
||||
if ((dev = malloc(strlen(argv[3]))) == NULL) {
|
||||
fprintf(stderr, "Fatal Error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memcpy(dev, argv[3], sizeof(dev));
|
||||
}
|
||||
else {
|
||||
dev = pcap_lookupdev(errbuf);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* print capture info */
|
||||
@ -72,8 +86,10 @@ int main(int argc, char **argv)
|
||||
dev_index = get_dev_index(dev);
|
||||
|
||||
/* set the WrapSix addresses */
|
||||
inet_aton("10.0.0.111", &ip4addr_wrapsix);
|
||||
inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
||||
//inet_aton("10.0.0.111", &ip4addr_wrapsix);
|
||||
//inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
||||
inet_aton(argv[1], &ip4addr_wrapsix);
|
||||
inet_pton(AF_INET6, argv[2], &ip6addr_wrapsix);
|
||||
|
||||
/* compile the filter expression */
|
||||
if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) {
|
||||
|
77
wrapsix.rb
77
wrapsix.rb
@ -3,63 +3,102 @@
|
||||
## WrapSix
|
||||
###
|
||||
#> wrapsix.rb
|
||||
#~ Description...
|
||||
#~ Main part of WrapSix that starts all other components
|
||||
####
|
||||
# Author: Michal Zima, 2008
|
||||
# E-mail: xhire@tuxportal.cz
|
||||
# Author: Michal Zima, 2008-2009
|
||||
# E-mail: xhire@tuxportal.cz
|
||||
# Homepage: http://wrapsix.tuxportal.cz/
|
||||
#####
|
||||
$version = '0.1.0'
|
||||
|
||||
### Hardcoded configuration => configured by system administrator
|
||||
$config = {}
|
||||
$config['config_file'] = 'conf/wrapsix.conf'
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
### Include all necessary libraries
|
||||
require 'yaml'
|
||||
require 'socket'
|
||||
require 'optparse'
|
||||
# WrapSix libs
|
||||
require 'lib/resolver'
|
||||
require 'lib/wrapper'
|
||||
|
||||
### Parse command line arguments if any
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Usage: wrapsix.rb [options]"
|
||||
|
||||
### Load configuration
|
||||
configuration = YAML.load_file $config['config_file']
|
||||
opts.on("--[no-]resolver", "Run the DNS resolver") do |resolver|
|
||||
$config['resolver'] = resolver
|
||||
end
|
||||
|
||||
## Merge both configs
|
||||
$config.merge! configuration # FIX: this overwrites those configs from command line!
|
||||
#p $config
|
||||
opts.on("--[no-]wrapper", "Run the wrapper") do |wrapper|
|
||||
$config['wrapper'] = wrapper
|
||||
end
|
||||
|
||||
### Start logging facility (system wide one)
|
||||
opts.on("--resolver-ip=IPv6_address", "Set the IPv6 address for the DNS resolver") do |rip|
|
||||
$config['resolver_ip'] = rip
|
||||
end
|
||||
|
||||
opts.on("--dns-resolver=IP_address", "Set the address of DNS resolver to be used") do |sr|
|
||||
$config['secondary_resolver'] = sr
|
||||
end
|
||||
|
||||
opts.on("--device=dev", "Set the network interface to override automatic detection") do |nic|
|
||||
$config['wrapper_device'] = nic
|
||||
end
|
||||
|
||||
opts.on("--ipv6=prefix", "Set the IPv6 preffix (max. /96), e.g. fc00::") do |prefix|
|
||||
$config['wrapper_ipv6_prefix'] = prefix
|
||||
end
|
||||
|
||||
opts.on("--ipv4=address", "Set the IPv4 address") do |addr|
|
||||
$config['wrapper_ipv4_address'] = addr
|
||||
end
|
||||
|
||||
opts.on("-d", "--[no-]debug", "Run in the debug mode") do |d|
|
||||
$config['debug'] = d
|
||||
end
|
||||
|
||||
opts.on_tail("-h", "--help", "Show this message") do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
|
||||
# Another typical switch to print the version.
|
||||
opts.on_tail("-v", "--version", "Show version") do
|
||||
puts "WrapSix #{$version}"
|
||||
puts "Copyright (c) 2008-2009 Michal Zima"
|
||||
exit
|
||||
end
|
||||
end.parse!
|
||||
|
||||
### Load configuration from file and merge it with the original one
|
||||
$config = YAML.load_file($config['config_file']).merge $config
|
||||
|
||||
### Handle some signals
|
||||
# todo: replace this with right variables
|
||||
def exit
|
||||
$resolver.exit if $config['resolver']
|
||||
$wrapper.exit if $config['wrapper']
|
||||
Process.exit
|
||||
end
|
||||
|
||||
# TERM -KILL- QUIT INT
|
||||
# TERM QUIT INT
|
||||
trap "INT" do; exit; end
|
||||
trap "TERM" do; exit; end
|
||||
trap "QUIT" do; exit; end
|
||||
|
||||
services = []
|
||||
### Start DNS resolver function
|
||||
if $config['resolver'] == 1
|
||||
$resolver = Resolver.new
|
||||
$resolver = Resolver.new
|
||||
if $config['resolver'] == true
|
||||
services << Thread.start do; $resolver.start; end
|
||||
end
|
||||
|
||||
### Start IPv6-to-IPv4 wrapper
|
||||
if $config['wrapper'] == 1
|
||||
$wrapper = Wrapper.new
|
||||
$wrapper = Wrapper.new
|
||||
if $config['wrapper'] == true
|
||||
services << Thread.start do; $wrapper.start; end
|
||||
end
|
||||
|
||||
### Start WrapSix
|
||||
# in best conditions it would *never* stop
|
||||
services.each do |srvc| srvc.join end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user