Compare commits

..

45 Commits

Author SHA1 Message Date
wangyu-
57be59e070 trival 2017-08-26 06:56:30 -05:00
wangyu-
fe77bb0c1a avoid allocating large buf on stack 2017-08-26 06:35:47 -05:00
wangyu-
cb9504f904 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-26 05:38:40 -05:00
wangyu-
dc4936dc60 implemented --lower-level auto for client. better makefile 2017-08-26 05:38:33 -05:00
wangyu-
53609c25fc Update openvpn_guide.md 2017-08-25 19:14:17 -07:00
wangyu-
60efcbce95 Merge pull request #35 from lance0/patch-1
typo and formatting.md
2017-08-25 08:55:51 -07:00
Lance Tuller
5c4ea515f6 Update README.md 2017-08-25 11:42:22 -04:00
Lance Tuller
e3b902a950 Update README.md
formatting and a typo :)
2017-08-25 11:40:48 -04:00
wangyu-
37f2de2ae4 Update openvpn_guide.md 2017-08-24 01:47:52 -07:00
wangyu-
ae497908a1 Update README.md 2017-08-24 01:06:51 -07:00
wangyu-
b59ba05422 Update README.md 2017-08-24 01:05:12 -07:00
wangyu-
cd34922722 Update README.md 2017-08-24 00:49:28 -07:00
wangyu-
51e5b023b0 Update README.md 2017-08-24 00:35:13 -07:00
wangyu-
b1800fa41a Update README.md 2017-08-24 00:23:58 -07:00
wangyu-
698ff33892 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-23 10:49:33 -05:00
wangyu-
1293b95335 bug fix and improve for conf 2017-08-23 10:47:09 -05:00
wangyu-
7e74b40977 Update README.zh-cn.md 2017-08-23 06:48:21 -07:00
wangyu-
d1e9bdc5da Update README.zh-cn.md 2017-08-23 06:47:05 -07:00
wangyu-
2b9d5c6db6 Update README.md 2017-08-23 06:24:46 -07:00
wangyu-
b86d475f1f moved cmakeLists 2017-08-23 07:23:02 -05:00
wangyu-
0a7f9b5cc6 fixed conf bugs and refactor 2017-08-23 07:01:21 -05:00
wangyu-
eb9633ed59 Update README.md 2017-08-22 22:08:51 -07:00
wangyu-
c0b464aeaf Update README.md 2017-08-22 22:08:04 -07:00
wangyu-
020242b73d Merge pull request #30 from PeterCxy/patch-config-file
Allow loading options from configuration files
2017-08-22 22:01:28 -07:00
Peter Cai
2269879a2e doc: note about comments 2017-08-23 11:22:33 +08:00
Peter Cai
057f81007d main: don't warn config-file as 'unknown' 2017-08-23 11:16:41 +08:00
Peter Cai
1f2f0d96fd main: fix missing includes 2017-08-23 11:09:46 +08:00
Peter Cai
01e0e51b9b config: treat TABs as spaces 2017-08-23 11:03:27 +08:00
Peter Cai
6ef38709a6 config: trim spaces and tabs 2017-08-23 11:03:24 +08:00
Peter Cai
57b874ee6d main: ignore empty lines in configuration 2017-08-23 11:03:21 +08:00
Peter Cai
ab0ce3ade3 main: merge cli/config arguments and check for duplications 2017-08-23 11:03:18 +08:00
Peter Cai
32f344fd3c README: document configuration files 2017-08-23 11:03:16 +08:00
Peter Cai
968d35178a main: allow loading configuration files (--config-file) 2017-08-23 11:03:12 +08:00
wangyu-
f8e268769c trival 2017-08-22 21:10:32 -05:00
wangyu-
b9030fe81d deleted useless headers 2017-08-22 11:00:44 -05:00
wangyu-
e6f0ed035c Update README.md 2017-08-22 00:58:04 -07:00
wangyu-
00e1ddfecc Update README.md 2017-08-21 21:20:24 -07:00
wangyu-
15e1790f73 Update README.md 2017-08-21 21:05:50 -07:00
wangyu-
763b0b7342 Update README.md 2017-08-21 21:03:16 -07:00
wangyu-
c716d617a0 Update README.md 2017-08-21 20:34:05 -07:00
wangyu-
60393d24d8 Merge pull request #33 from YUChoe/master
Fix Typo TCP over TCP
2017-08-21 20:04:30 -07:00
Yong-uk Choe
9e7ed280fc Fix Typo TCP over TCP 2017-08-22 09:44:19 +09:00
root
532693edc6 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-21 23:32:21 +08:00
root
033fa830f7 trival 2017-08-21 23:31:55 +08:00
wangyu-
51464ecbfe Update README.zh-cn.md 2017-08-21 08:07:06 -07:00
14 changed files with 848 additions and 217 deletions

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.436825263">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.436825263" moduleId="org.eclipse.cdt.core.settings" name="Default">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1051378038">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1051378038" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
@@ -14,28 +14,17 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.436825263" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.436825263.480908490" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1517253393" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.GNU_ELF" id="cdt.managedbuild.target.gnu.platform.base.1797790700" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.base.1253245139" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.2108168419" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1940762076" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.997669137" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.233419498" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.460189617" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.54583610" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.2065407163" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.263855663" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.747872161" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1349563828" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
<configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.base.1051378038" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1051378038.1421447843" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1854135910" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.GNU_ELF" id="cdt.managedbuild.target.gnu.platform.base.708367396" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.base.1743684210" managedBuildOn="false" name="Gnu Make Builder.Default" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1848194835" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1873425854" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"/>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1356109619" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"/>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1018655568" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.180014749" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.2017907772" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"/>
</toolChain>
</folderInfo>
</configuration>
@@ -43,16 +32,6 @@
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="udp2raw-tunnel-desktop.null.370025459" name="udp2raw-tunnel-desktop"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/udp2raw-tunnel-desktop"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.436825263;cdt.managedbuild.toolchain.gnu.base.436825263.480908490;cdt.managedbuild.tool.gnu.cpp.compiler.base.1940762076;cdt.managedbuild.tool.gnu.cpp.compiler.input.997669137">
@@ -62,5 +41,8 @@
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="udp2raw.null.1592488805" name="udp2raw"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View File

@@ -1,21 +1,23 @@
# Udp2raw-tunnel
![image0](images/image0.PNG)
A UDP Tunnel which tunnels UDP via FakeTCP/UDP/ICMP Traffic by using Raw Socket,helps you Bypass UDP FireWalls(or Unstable UDP Environment).Its Encrpyted,Anti-Replay and Multiplexed.It aslo acts as a Connection Stablizer.
A Tunnel which tunnels UDP via FakeTCP/UDP/ICMP Traffic by using Raw Socket, helps you Bypass UDP FireWalls(or Unstable UDP Environment). Its Encrypted, Anti-Replay and Multiplexed. It also acts as a Connection Stabilizer.
[简体中文](/doc/README.zh-cn.md)
# Support Platforms
A Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root access.
Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root access.
For Winodws/MacOS,virtual image with udp2raw pre-installed has been released,you can load it with Vmware/VirtualBox.The virtual image has been set to auto obtain ip,udp2raw can be run imidiately after boot finished(make sure network mode of virtual machine has been set to bridged)(only udp2raw has to be run under virtual machine,all other programs runs under Windows/MacOS as usual).
For Winodws/MacOS,the 4.4mb virtual image with udp2raw pre-installed has been released,you can load it with Vmware/VirtualBox.The virtual image has been set to auto obtain ip,udp2raw can be run imidiately after boot finished(make sure network mode of virtual machine has been set to bridged)(only udp2raw has to be run under virtual machine,all other programs runs under Windows/MacOS as usual).
# Features
### Send / Receive UDP Packet with fake-tcp/icmp headers
Fake-tcp/icmp headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. Raw packets with UDP headers are also supported.In UDP header mode,it behaves just like a normal UDP tunnel,and you can just make use of the other features.
### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers
ICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.
### Simulate TCP Handshake
Simulates the 3-way handshake, along with seq and ack_seq. TCP options MSS, sackOk, TS, TS_ack, wscale are also simulated. Real-time delivery guaranteed, no TCP over TCP problem when using OpenVPN.
UDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encrytion, anti-replay, or connection stalization).
### Simulated TCP with Real-time/Out-of-Order Delivery
In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates following TCP options: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`.Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congrestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.
### Encrpytion, Anti-Replay
* Encrypt your traffic with AES-128-CBC.
@@ -23,9 +25,9 @@ Simulates the 3-way handshake, along with seq and ack_seq. TCP options MSS, sack
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
### Failure Dectection & Stablization (Connection Recovery)
Conection failures are detected by heartbeats. If timed-out,client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild.
Conection failures are detected by heartbeats. If timed-out, client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild.
For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if the network cable is re-plugged or the WiFi access point is changed**.
For example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if network cable is re-plugged or WiFi access point is changed**.
### Other Features
* **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection.
@@ -34,12 +36,12 @@ For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after a
* **NAT Support** All of the 3 modes work in NAT environments.
* **OpenVZ Support** Tested on BandwagonHost.
* **OpenVZ Support** Tested on BandwagonHost VPS.
* **OpenWRT Support** No dependencies, easy to build. Binary for ar71xx are included in release.
* **Easy to Build** No dependencies.To cross-compile udp2raw,all you need to do is just to download a toolchain,modify makefile to point at the toolchain,run `make cross` then everything is done.(Note:Pre-compiled binaries for Desktop,RaspberryPi,Android,some Openwrt Routers are already included in [Releases](https://github.com/wangyu-/udp2raw-tunnel/releases))
### Keywords
`UDP QoS Bypass` `UDP Blocking Bypass` `OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
# Getting Started
### Installing
@@ -63,7 +65,7 @@ Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your
Now,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed.
### Note
to run on Android, see [Android_Guide](/doc/android_guide.md)
To run on Android, check [Android_Guide](/doc/android_guide.md)
# Advanced Topic
### Usage
@@ -89,6 +91,7 @@ client options:
--source-port <port> force source-port for raw socket,tcp/udp only
this option disables port changing while re-connecting
other options:
--conf-file <string> read options from a configuration file instead of command line
--log-level <number> 0:never 1:fatal 2:error 3:warn
4:info (default) 5:debug 6:trace
--log-position enable file name,function name,line number in log
@@ -105,15 +108,46 @@ other options:
-h,--help print this help message
```
### IPTABLES rule
### Iptables rules,`-a` and `-g`
This program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.
### `cipher-mode` and `auth-mode`
### `--cipher-mode` and `--auth-mode`
It is suggested to use `aes128cbc` + `md5` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.
### seq-mode
### `--seq-mode`
The FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.
### `--conf-file`
You can also load options from a configuration file in order to keep secrets away from ps command.
For example, rewrite the options for the above `server` example (in Getting Started section) into configuration file:
`server.conf`
```
-s
# You can add comments like this
# Comments MUST occupy an entire line
# Or they will not work as expected
# Listen address
-l 0.0.0.0:4096
# Remote address
-r 127.0.0.1:7777
-a
-k passwd
--raw-mode faketcp
```
Pay attention to the `-k` parameter: In command line mode the quotes around the password will be removed by shell. In configuration files we do not remove quotes.
Then start the server with
```bash
./udp2raw_amd64 --conf-file server.conf
```
# Peformance Test
#### Test method:
iperf3 TCP via OpenVPN + udp2raw
@@ -147,7 +181,7 @@ raw_mode: faketcp cipher_mode: aes128cbc  auth_mode: md5
![image_vpn](images/openvpn.PNG)
1. Bypasses UDP block/UDP QOS
2. No TCP ovr TCP problem (TCP over TCP problem http://sites.inka.de/bigred/devel/tcp-tcp.html ,https://community.openvpn.net/openvpn/ticket/2 )
2. No TCP over TCP problem (TCP over TCP problem http://sites.inka.de/bigred/devel/tcp-tcp.html ,https://community.openvpn.net/openvpn/ticket/2 )
3. OpenVpn over ICMP also becomes a choice

View File

@@ -15,6 +15,7 @@ int about_to_exit=0;
raw_mode_t raw_mode=mode_faketcp;
unordered_map<int, const char*> raw_mode_tostring = {{mode_faketcp, "faketcp"}, {mode_udp, "udp"}, {mode_icmp, "icmp"}};
int socket_buf_size=1024*1024;
static int random_number_fd=-1;
string iptables_pattern="";
int iptables_rule_added=0;
@@ -152,6 +153,7 @@ int iptables_rule_init(const char * s,u32_t const_id,int keep)
myexit(-1);
}
}
mylog(log_warn,"auto added iptables rules\n");
return 0;
}
@@ -388,7 +390,31 @@ int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3)
id3=ntohl( *((id_t*)(data+sizeof(id_t)*2)) );
return 0;
}
int hex_to_u32(const string & a,u32_t &output)
{
//string b="0x";
//b+=a;
if(sscanf(a.c_str(),"%x",&output)==1)
{
//printf("%s %x\n",a.c_str(),output);
return 0;
}
mylog(log_error,"<%s> doesnt contain a hex\n",a.c_str());
return -1;
}
int hex_to_u32_with_endian(const string & a,u32_t &output)
{
//string b="0x";
//b+=a;
if(sscanf(a.c_str(),"%x",&output)==1)
{
output=htonl(output);
//printf("%s %x\n",a.c_str(),output);
return 0;
}
mylog(log_error,"<%s> doesnt contain a hex\n",a.c_str());
return -1;
}
bool larger_than_u32(u32_t a,u32_t b)
{
@@ -458,8 +484,13 @@ vector<string> string_to_vec(const char * s,const char * sp) {
{
res.push_back(p);
//printf ("%s\n",p);
p = strtok (NULL, sp);
p = strtok(NULL, sp);
}
/* for(int i=0;i<(int)res.size();i++)
{
printf("<<%s>>\n",res[i].c_str());
}*/
return res;
}
@@ -475,33 +506,38 @@ vector< vector <string> > string_to_vec2(const char * s)
}
return res;
}
int read_file(const char * file,char * &output)
int read_file(const char * file,string &output)
{
static char buf[1024*1024+100];
buf[sizeof(buf)-1]=0;
const int max_len=3*1024*1024;
// static char buf[max_len+100];
string buf0;
buf0.reserve(max_len+200);
char * buf=(char *)buf0.c_str();
buf[max_len]=0;
//buf[sizeof(buf)-1]=0;
int fd=open(file,O_RDONLY);
if(fd==-1)
{
mylog(log_error,"read_file %s fail\n",file);
return -1;
}
int len=read(fd,buf,1024*1024);
if(len==1024*1024)
int len=read(fd,buf,max_len);
if(len==max_len)
{
buf[0]=0;
mylog(log_error,"too long,buf not larger enough\n");
mylog(log_error,"%s too long,buf not large enough\n",file);
return -2;
}
else if(len<0)
{
buf[0]=0;
mylog(log_error,"read fail %d\n",len);
mylog(log_error,"%s read fail %d\n",file,len);
return -3;
}
else
{
output=buf;
buf[len]=0;
output=buf;
}
return 0;
}
@@ -607,3 +643,87 @@ int run_command_no_log(string command0,char * &output) {
return 0;
}*/
// Remove preceding and trailing characters
string trim(const string& str, char c) {
size_t first = str.find_first_not_of(c);
if(string::npos==first)
{
return "";
}
size_t last = str.find_last_not_of(c);
return str.substr(first,(last-first+1));
}
vector<string> parse_conf_line(const string& s0)
{
string s=s0;
s.reserve(s.length()+200);
char *buf=(char *)s.c_str();
//char buf[s.length()+200];
char *p=buf;
int i=int(s.length())-1;
int j;
vector<string>res;
strcpy(buf,(char *)s.c_str());
while(i>=0)
{
if(buf[i]==' ' || buf[i]== '\t')
buf[i]=0;
else break;
i--;
}
while(*p!=0)
{
if(*p==' ' || *p== '\t')
{
p++;
}
else break;
}
int new_len=strlen(p);
if(new_len==0)return res;
if(p[0]=='#') return res;
if(p[0]!='-')
{
mylog(log_fatal,"line :<%s> not begin with '-' ",s.c_str());
myexit(-1);
}
for(i=0;i<new_len;i++)
{
if(p[i]==' '||p[i]=='\t')
{
break;
}
}
if(i==new_len)
{
res.push_back(p);
return res;
}
j=i;
while(p[j]==' '||p[j]=='\t')
j++;
p[i]=0;
res.push_back(p);
res.push_back(p+j);
return res;
}

View File

@@ -159,11 +159,19 @@ const int show_log=0x2;
const int show_all=show_command|show_log;
int run_command(string command,char * &output,int flag=show_all);
//int run_command_no_log(string command,char * &output);
int read_file(const char * file,char * &output);
int read_file(const char * file,string &output);
vector<string> string_to_vec(const char * s,const char * sp);
vector< vector <string> > string_to_vec2(const char * s);
string trim(const string& str, char c);
string trim_conf_line(const string& str);
vector<string> parse_conf_line(const string& s);
int hex_to_u32_with_endian(const string & a,u32_t &output);
int hex_to_u32(const string & a,u32_t &output);
//extern string iptables_pattern;
#endif /* COMMON_H_ */

16
config.example Normal file
View File

@@ -0,0 +1,16 @@
# Basically this file is the equivalent to splitting the command line options into multiple lines
# Each line should contain an option
# This is client
-c
# Or use -s if you use it on server side
# Define local address
-l 127.0.0.1:56789
# Define remote address
-r 45.66.77.88:45678
# Password
-k my_awesome_password
# Mode
--raw-mode faketcp
# Log Level
--log-level 4

View File

@@ -123,17 +123,18 @@ other options:
ie:'eth0#00:23:45:67:89:b9'.Beta.
-h,--help print this help message
```
### iptables 规则
### iptables 规则,`-a`和`-g`
用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识如果一直收到不认识的包会回复大量RST造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项udp2raw会在启动的时候自动帮你加上Iptables规则退出的时候再自动删掉。如果长期使用可以用-g选项来生成相应的Iptables规则再自己手动添加这样规则不会在udp2raw退出时被删掉可以避免停掉udp2raw后内核向对端回复RST。
用raw收发udp包也类似只是内核回复的是icmp unreachable。而用raw 收发icmp内核会自动回复icmp echo。都需要相应的iptables规则。
### cipher-mode 和 auth-mode
### `--cipher-mode``--auth-mode`
如果要最大的安全性建议用aes128cbc+md5。如果要运行再路由器上建议xor+simple。但是注意xor+simple只能骗过防火墙的包检测不能防止真正的攻击者。
### seq-mode
### `--seq-mode`
facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来虽然大部分ISP不太可能做这种程度的包检测。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题可以尝试更改。在我这边的移动线路用3种模式都没问题。
### lower-level
### `--lower-level`
大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效比如你用的是梅林固件iptables全是固件自己生成的
##### 格式
@@ -148,11 +149,40 @@ facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和
如果client没有公网ip`traceroute google.com``traceroute baidu.com`。下一步和client端的方法一样。
server端也可以用`--lower-level auto` 来尝试自动获得参数,如果无法连接再手动填写。
##### 注意
如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。
如果`arps -s`命令查询不到首先再试几次。如果还是查询不到那么可能是因为你用的是pppoe方式的拨号宽带查询不到是正常的。这种情况下`if_name`填pppoe产生的虚拟interface通常名字叫`pppXXXX`,从`ifconfig`命令的输出里找一下;`des_mac_adress``00:00:00:00:00:00`,例如`ppp0#00:00:00:00:00:00`
### `--conf-file`
为了避免将密码等私密信息暴露在进程命令行参数内,你也可以使用 `配置文件` 来存储参数。
比如,将以上服务端参数改写成配置文件
`server.conf`:
```
-s
# 你可以像这样添加注释
# 注意,只有整行注释才能在配置文件里使用
# 注释必须独占一行
-l 0.0.0.0:4096
-r 127.0.0.1:7777
-a
-k passwd
--raw-mode faketcp
```
注意,当写入配置文件的时候,密码等参数两边的引号必须去除。
然后就可以使用下面的方式启动服务端
```bash
./udp2raw_amd64 --conf-file server.conf
```
# 性能测试
iperf3 的UDP模式有BUG所以这里用iperf3的tcp模式配合Openvpn测试udp2raw的性能。iperf3 udp issue ,https://github.com/esnet/iperf/issues/296

View File

@@ -2,6 +2,7 @@
![image_vpn](/images/openvpn.PNG)
![image4](/images/image4.PNG)
# udp2raw command
#### run at server side
```
@@ -13,6 +14,8 @@ assume server ip is 45.66.77.88
./udp2raw_amd64 -s -l0.0.0.0:3333 -r 45.66.77.88:8855 -k "passwd" --raw-mode faketcp -a
```
#### hint
You can add `--cipher-mode xor` `--auth-mode simple` to **both** sides to obtain maximum performance(but poor security).
# openvpn config

View File

@@ -12,10 +12,10 @@
static int8_t zero_iv[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0};//this prog use zero iv,you should make sure first block of data contains a random/nonce data
/****
* important!
* why zero iv + nonce first data block is secure?
* security of zero_iv + nonce first data block
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
****/
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"}};
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"}};

50
log.h
View File

@@ -2,56 +2,8 @@
#ifndef _LOG_MYLOG_H_
#define _LOG_MYLOG_H_
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<getopt.h>
#include <unistd.h>
#include<errno.h>
#include <fcntl.h>
//#include"aes.h"
#include <sys/epoll.h>
#include <sys/wait.h>
#include<map>
#include<string>
#include<vector>
#include <sys/socket.h> //for socket ofcourse
#include <sys/types.h>
#include <stdlib.h> //for exit(0);
#include <errno.h> //For errno - the error number
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/udp.h>
#include <netinet/ip.h> //Provides declarations for ip header
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <byteswap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <sys/time.h>
#include <time.h>
#include <sys/timerfd.h>
#include <set>
#include "encrypt.h"
#include <inttypes.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include<common.h>
using namespace std;

411
main.cpp
View File

@@ -2,6 +2,12 @@
#include "network.h"
#include "log.h"
#include "lib/md5.h"
#include "encrypt.h"
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";
u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;
@@ -569,6 +575,8 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len);
int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * data, int data_len);
void process_arg(int argc, char *argv[]);
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
int DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
////////////////=======================declear divider=============================
@@ -1981,10 +1989,12 @@ int client_event_loop()
{
if(lower_level_manual)
{
int index;
init_ifindex(if_name,index);
//init_ifindex(if_name);
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family = AF_PACKET;
send_info.addr_ll.sll_ifindex = ifindex;
send_info.addr_ll.sll_ifindex =index;
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
@@ -1992,8 +2002,39 @@ int client_event_loop()
}
else
{
mylog(log_fatal,"--lower-level auto for client hasnt been implemented\n");
myexit(-1);
u32_t dest_ip;
string if_name_string;
string hw_string;
if(find_lower_level_info(remote_ip_uint32,dest_ip,if_name_string,hw_string)!=0)
{
mylog(log_fatal,"auto detect lower-level info failed for %s,specific it manually\n",remote_ip);
myexit(-1);
}
mylog(log_info,"we are running at lower-level (auto) mode,%s %s %s\n",my_ntoa(dest_ip),if_name_string.c_str(),hw_string.c_str());
u32_t hw[6];
memset(hw, 0, sizeof(hw));
sscanf(hw_string.c_str(), "%x:%x:%x:%x:%x:%x",&hw[0], &hw[1], &hw[2],
&hw[3], &hw[4], &hw[5]);
mylog(log_warn,
"make sure this is correct: if_name=<%s> dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x> \n",
if_name_string.c_str(), hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
for (int i = 0; i < 6; i++) {
dest_hw_addr[i] = uint8_t(hw[i]);
}
//mylog(log_fatal,"--lower-level auto for client hasnt been implemented\n");
int index;
init_ifindex(if_name_string.c_str(),index);
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family = AF_PACKET;
send_info.addr_ll.sll_ifindex = index;
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
//mylog(log_info,"we are running at lower-level (manual) mode\n");
}
}
@@ -2214,6 +2255,19 @@ int server_event_loop()
bind_address_uint32=local_ip_uint32;//only server has bind adress,client sets it to zero
if(lower_level)
{
if(lower_level_manual)
{
init_ifindex(if_name,ifindex);
mylog(log_info,"we are running at lower-level (manual) mode\n");
}
else
{
mylog(log_info,"we are running at lower-level (auto) mode\n");
}
}
if(raw_mode==mode_faketcp)
{
@@ -2448,13 +2502,7 @@ int process_lower_level_arg()
lower_level=1;
if(strcmp(optarg,"auto")==0)
{
if(program_mode==server_mode)
return 0;
else
{
mylog(log_fatal,"--lower-level auto hasnt be implement at client side,specify it manually\n");
myexit(-1);
}
return 0;
}
lower_level_manual=1;
@@ -2493,7 +2541,8 @@ void print_help()
printf(" --cipher-mode <string> avaliable values:aes128cbc(default),xor,none\n");
printf(" --auth-mode <string> avaliable values:md5(default),crc32,simple,none\n");
printf(" -a,--auto-rule auto add (and delete) iptables rule\n");
printf(" -g,--gen-rule generate iptables rule then exit,overrides -a\n");
printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");
printf(" add it manually.overrides -a\n");
printf(" --disable-anti-replay disable anti-replay,not suggested\n");
//printf("\n");
@@ -2503,6 +2552,7 @@ void print_help()
printf(" this option disables port changing while re-connecting\n");
// printf(" \n");
printf("other options:\n");
printf(" --conf-file <string> read options from a configuration file instead of command line\n");
printf(" --log-level <number> 0:never 1:fatal 2:error 3:warn \n");
printf(" 4:info (default) 5:debug 6:trace\n");
// printf("\n");
@@ -2526,51 +2576,53 @@ void print_help()
//printf("common options,these options must be same on both side\n");
}
void process_arg(int argc, char *argv[])
{
int i,j,k,opt;
static struct option long_options[] =
{
/* These options set a flag. */
{"source-ip", required_argument, 0, 1},
{"source-port", required_argument, 0, 1},
{"log-level", required_argument, 0, 1},
{"key", required_argument, 0, 'k'},
{"auth-mode", required_argument, 0, 1},
{"cipher-mode", required_argument, 0, 1},
{"raw-mode", required_argument, 0, 1},
{"disable-color", no_argument, 0, 1},
{"log-position", no_argument, 0, 1},
{"disable-bpf", no_argument, 0, 1},
{"disable-anti-replay", no_argument, 0, 1},
{"auto-rule", no_argument, 0, 'a'},
{"gen-rule", no_argument, 0, 'g'},
{"gen-add", no_argument, 0, 1},
{"debug", no_argument, 0, 1},
{"clear", no_argument, 0, 1},
{"simple-rule", no_argument, 0, 1},
{"keep-rule", no_argument, 0, 1},
{"lower-level", required_argument, 0, 1},
{"sock-buf", required_argument, 0, 1},
{"seq-mode", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
int option_index = 0;
for (i = 0; i < argc; i++)
int load_config(char *file_name, int &argc, vector<string> &argv)
{
// Load configurations from config_file instead of the command line.
// See config.example for example configurations
std::ifstream conf_file(file_name);
std::string line;
if(conf_file.fail())
{
if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
{
print_help();
myexit(0);
}
}
if (argc == 1)
{
print_help();
mylog(log_fatal,"conf_file %s open failed,reason :%s\n",file_name,strerror(errno));
myexit(-1);
}
while(std::getline(conf_file,line))
{
auto res=parse_conf_line(line);
argc+=res.size();
for(int i=0;i<(int)res.size();i++)
{
argv.push_back(res[i]);
}
}
conf_file.close();
return 0;
}
int unit_test()
{
printf("running unit test\n");
vector<string> conf_lines= {"---aaa","--aaa bbb","-a bbb"," \t \t \t-a\t \t \t bbbbb\t \t \t "};
for(int i=0;i<int(conf_lines.size());i++)
{
printf("orign:%s\n",conf_lines[i].c_str());
auto res=parse_conf_line(conf_lines[i]);
printf("pasrse_result: size %d",int(res.size()));
for(int j=0;j<int(res.size());j++)
{
printf("<%s>",res[j].c_str());
}
printf("\n");
}
return 0;
}
int process_log_level(int argc,char *argv[])
{
int i,j,k;
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"--log-level")==0)
@@ -2592,19 +2644,143 @@ void process_arg(int argc, char *argv[])
{
enable_log_color=0;
}
if(strcmp(argv[i],"--log-position")==0)
{
enable_log_position=1;
}
}
return 0;
}
void process_arg(int argc, char *argv[])
{
int i,j,k,opt;
int option_index = 0;
char options[]="l:r:schk:ag";
static struct option long_options[] =
{
/* These options set a flag. */
{"source-ip", required_argument, 0, 1},
{"source-port", required_argument, 0, 1},
{"log-level", required_argument, 0, 1},
{"key", required_argument, 0, 'k'},
{"auth-mode", required_argument, 0, 1},
{"cipher-mode", required_argument, 0, 1},
{"raw-mode", required_argument, 0, 1},
{"disable-color", no_argument, 0, 1},
{"log-position", no_argument, 0, 1},
{"disable-bpf", no_argument, 0, 1},
{"disable-anti-replay", no_argument, 0, 1},
{"auto-rule", no_argument, 0, 'a'},
{"gen-rule", no_argument, 0, 'g'},
{"gen-add", no_argument, 0, 1},
{"debug", no_argument, 0, 1},
{"clear", no_argument, 0, 1},
{"simple-rule", no_argument, 0, 1},
{"keep-rule", no_argument, 0, 1},
{"lower-level", required_argument, 0, 1},
{"sock-buf", required_argument, 0, 1},
{"seq-mode", required_argument, 0, 1},
{"conf-file", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
process_log_level(argc,argv);
set<string> all_options;
map<string,string> shortcut_map;
all_options.insert("--help");
all_options.insert("-h");
string dummy="";
for(i=0;i<(int)strlen(options);i++)
{
char val=options[i];
if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
{
all_options.insert(dummy+'-'+val);
}
}
for(i=0;i<int( sizeof(long_options)/sizeof(long_options[0]) );i++)
{
if(long_options[i].name==NULL) break;
int val=long_options[i].val;
if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
{
shortcut_map[dummy+"--"+long_options[i].name]= dummy+"-"+ char(val);
}
all_options.insert(dummy+"--"+long_options[i].name);
}
for (i = 0; i < argc; i++)
{
int len=strlen(argv[i]);
if(len==0)
{
mylog(log_fatal,"found an empty string in options\n");
myexit(-1);
}
if(len==1&&argv[i][0]=='-' )
{
mylog(log_fatal,"invaild option '-' in argv\n");
myexit(-1);
}
if(len==2&&argv[i][0]=='-'&&argv[i][1]=='-' )
{
mylog(log_fatal,"invaild option '--' in argv\n");
myexit(-1);
}
}
mylog(log_info,"argc=%d ", argc);
mylog(log_info,"argc=%d ", argc);
for (i = 0; i < argc; i++) {
log_bare(log_info, "%s ", argv[i]);
}
log_bare(log_info, "\n");
//string dummy="";
for(i=+1;i<argc;i++)
{
if(argv[i][0]!='-') continue;
string a=argv[i];
if(a[0]=='-'&&a[1]!='-')
a=dummy+a[0]+a[1];
if(all_options.find(a.c_str())==all_options.end())
{
mylog(log_fatal,"invaild option %s\n",a.c_str());
myexit(-1);
}
for(j=i+1;j<argc;j++)
{
if(argv[j][0]!='-') continue;
string b=argv[j];
if(b[0]=='-'&&b[1]!='-')
b=dummy+b[0]+b[1];
if(shortcut_map.find(a)!=shortcut_map.end())
a=shortcut_map[a];
if(shortcut_map.find(b)!=shortcut_map.end())
b=shortcut_map[b];
if(a==b)
{
mylog(log_fatal,"%s duplicates with %s\n",argv[i],argv[j]);
myexit(-1);
}
}
}
int no_l = 1, no_r = 1;
while ((opt = getopt_long(argc, argv, "l:r:schk:ag",long_options,&option_index)) != -1) {
while ((opt = getopt_long(argc, argv,options,long_options,&option_index)) != -1) {
//string opt_key;
//opt_key+=opt;
switch (opt) {
@@ -2723,6 +2899,10 @@ void process_arg(int argc, char *argv[])
if(strcmp(optarg,auth_mode_tostring[i])==0)
{
auth_mode=(auth_mode_t)i;
if(auth_mode==auth_none)
{
disable_anti_replay=1;
}
break;
}
}
@@ -2785,7 +2965,7 @@ void process_arg(int argc, char *argv[])
}
else if(strcmp(long_options[option_index].name,"log-position")==0)
{
enable_log_position=1;
//enable_log_position=1;
}
else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
{
@@ -2821,6 +3001,10 @@ void process_arg(int argc, char *argv[])
myexit(-1);
}
}
else if(strcmp(long_options[option_index].name,"conf-file")==0)
{
mylog(log_info,"configuration loaded from %s\n",optarg);
}
else
{
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
@@ -2866,7 +3050,93 @@ void process_arg(int argc, char *argv[])
log_bare(log_info,"\n");
}
void pre_process_arg(int argc, char *argv[])
{
int i,j,k;
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"--unit-test")==0)
{
unit_test();
myexit(0);
}
}
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
{
print_help();
myexit(0);
}
}
if (argc == 1)
{
print_help();
myexit(-1);
}
process_log_level(argc,argv);
int new_argc=0;
vector<string> new_argv;
int count=0;
int pos=-1;
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"--conf-file")==0)
{
count++;
pos=i;
if(i==argc)
{
mylog(log_fatal,"--conf-file need a parameter\n");
myexit(-1);
}
if(argv[i+1][0]=='-')
{
mylog(log_fatal,"--conf-file need a parameter\n");
myexit(-1);
}
i++;
}
else
{
//printf("<%s>",argv[i]);
new_argc++;
new_argv.push_back(argv[i]);
}
}
if(count>1)
{
mylog(log_fatal,"duplicated --conf-file option\n");
myexit(-1);
}
if(count>0)
{
load_config(argv[pos+1],new_argc,new_argv);
}
char* new_argv_char[new_argv.size()];
new_argc=0;
for(i=0;i<(int)new_argv.size();i++)
{
if(strcmp(new_argv[i].c_str(),"--conf-file")==0)
{
mylog(log_fatal,"cant have --conf-file in a config file\n");
myexit(-1);
}
new_argv_char[new_argc++]=(char *)new_argv[i].c_str();
}
process_arg(new_argc,new_argv_char);
}
void *run_keep(void *none)
{
@@ -3004,29 +3274,24 @@ void iptables_rule()
}
/*
int test()
{
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
return 0;
char ip_str[100]="8.8.8.8";
u32_t ip=inet_addr(ip_str);
u32_t dest_ip;
string if_name;
string hw;
find_lower_level_info(ip,dest_ip,if_name,hw);
printf("%s %s %s\n",my_ntoa(dest_ip),if_name.c_str(),hw.c_str());
exit(0);
return 0;
}*/
int main(int argc, char *argv[])
{
//test();
printf("%s\n",my_ntoa(0x00ffffff));
//auto a=string_to_vec("a b c d ");
//printf("%d\n",(int)a.size());
@@ -3039,7 +3304,7 @@ int main(int argc, char *argv[])
signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler);
process_arg(argc,argv);
pre_process_arg(argc,argv);
if(geteuid() != 0)
{
@@ -3078,10 +3343,6 @@ int main(int argc, char *argv[])
iptables_rule();
init_raw_socket();
if(lower_level_manual)
{
init_ifindex(if_name);
}
if(program_mode==client_mode)
{

View File

@@ -1,47 +1,51 @@
cc_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++
cc_local=g++
cc_ar71xx=/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
cc_arm=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++
cc_mips34kc=/toolchains/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
SOURCES=main.cpp lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -lpthread
SOURCES=main.cpp lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lpthread
SOURCES_AES_ACC=$(filter-out lib/aes.c,$(SOURCES)) $(wildcard lib/aes_acc/aes*.c)
NAME=udp2raw
TAR=${NAME}_binaries.tar.gz ${NAME}_amd64 ${NAME}_x86 ${NAME}_x86_asm_aes ${NAME}_ar71xx ${NAME}_bcm2708 ${NAME}_arm ${NAME}_amd64_hw_aes ${NAME}_arm_asm_aes ${NAME}_ar71xx_asm_aes
TARGETS=amd64 mips34kc arm amd64_hw_aes arm_asm_aes mips34kc_asm_aes x86 x86_asm_aes
TAR=${NAME}_binaries.tar.gz `echo ${TARGETS}|sed -r 's/([^ ]+)/udp2raw_\1/g'`
all:
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -static -O3
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O3
fast:
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb
debug:
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
debug2:
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -ggdb
ar71xx:
${cc_ar71xx} -o ${NAME}_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
mips34kc:
${cc_mips34kc} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
ar71xx_asm_aes:
${cc_ar71xx} -o ${NAME}_ar71xx_asm_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -lgcc_eh -static -O3 lib/aes_acc/asm/mips_be.S
mips34kc_asm_aes:
${cc_mips34kc} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -lgcc_eh -static -O3 lib/aes_acc/asm/mips_be.S
bcm2708:
${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
#bcm2708:
# ${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64:
${cc_local} -o ${NAME}_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64_hw_aes:
${cc_local} -o ${NAME}_amd64_hw_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/x64.S
${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/x64.S
x86:
${cc_local} -o ${NAME}_x86 -I. ${SOURCES} ${FLAGS} -lrt -static -O3 -m32
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3 -m32
x86_asm_aes:
${cc_local} -o ${NAME}_x86_asm_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 -m32 lib/aes_acc/asm/x86.S
${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 -m32 lib/aes_acc/asm/x86.S
arm:
${cc_cross} -o ${NAME}_arm -I. ${SOURCES} ${FLAGS} -lrt -static -O3
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
arm_asm_aes:
${cc_cross} -o ${NAME}_arm_asm_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/arm.S
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/arm.S
cross:
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
@@ -52,7 +56,7 @@ cross2:
cross3:
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -O3
release: amd64 x86 ar71xx bcm2708 arm amd64_hw_aes arm_asm_aes x86_asm_aes ar71xx_asm_aes
release: ${TARGETS}
tar -zcvf ${TAR}
clean:

View File

@@ -289,7 +289,7 @@ void remove_filter()
//exit(-1);
}
}
int init_ifindex(char * if_name)
int init_ifindex(const char * if_name,int &index)
{
struct ifreq ifr;
size_t if_name_len=strlen(if_name);
@@ -305,10 +305,230 @@ int init_ifindex(char * if_name)
mylog(log_fatal,"SIOCGIFINDEX fail ,%s\n",strerror(errno));
myexit(-1);
}
ifindex=ifr.ifr_ifindex;
mylog(log_info,"ifname:%s ifindex:%d\n",if_name,ifindex);
index=ifr.ifr_ifindex;
mylog(log_info,"ifname:%s ifindex:%d\n",if_name,index);
return 0;
}
bool interface_has_arp(const char * interface) {
struct ifreq ifr;
// int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
int sock=raw_send_fd;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, interface);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
//perror("SIOCGIFFLAGS");
mylog(log_fatal,"ioctl(sock, SIOCGIFFLAGS, &ifr) failed for interface %s,errno %s\n",interface,strerror(errno));
myexit(-1);
}
//close(sock);
return !(ifr.ifr_flags & IFF_NOARP);
}
struct route_info_t
{
string if_name;
u32_t dest;
u32_t mask;
u32_t gw;
u32_t flag;
};
int dest_idx=1;
int gw_idx=2;
int if_idx=0;
int mask_idx=7;
int flag_idx=3;
vector<int> find_route_entry(const vector<route_info_t> &route_info_vec,u32_t ip)
{
vector<int> res;
for(u32_t i=0;i<=32;i++)
{
u32_t mask=0xffffffff;
//mask >>=i;
//if(i==32) mask=0; //why 0xffffffff>>32 equals 0xffffffff??
mask <<=i;
if(i==32) mask=0;
log_bare(log_debug,"(mask:%x)",mask);
for(u32_t j=0;j<route_info_vec.size();j++)
{
const route_info_t & info=route_info_vec[j];
if(info.mask!=mask)
continue;
log_bare(log_debug,"<<%d,%d>>",i,j);
if((info.dest&mask)==(ip&mask))
{
log_bare(log_debug,"found!");
res.push_back(j);
}
}
if(res.size()!=0)
{
return res;
}
}
return res;
}
int find_direct_dest(const vector<route_info_t> &route_info_vec,u32_t ip,u32_t &dest_ip,string &if_name)
{
vector<int> res;
for(int i=0;i<1000;i++)
{
res=find_route_entry(route_info_vec,ip);
log_bare(log_debug,"<entry:%u>",(u32_t)res.size());
if(res.size()==0)
{
mylog(log_error,"cant find route entry\n");
return -1;
}
if(res.size()>1)
{
mylog(log_error,"found duplicated entries\n");
return -1;
}
if((route_info_vec[res[0]].flag&2)==0)
{
dest_ip=ip;
if_name=route_info_vec[res[0]].if_name;
return 0;
}
else
{
ip=route_info_vec[res[0]].gw;
}
}
mylog(log_error,"dead loop in find_direct_dest\n");
return -1;
}
struct arp_info_t
{
u32_t ip;
string hw;
string if_name;
};
int arp_ip_idx=0;
int arp_hw_idx=3;
int arp_if_idx=5;
int find_arp(const vector<arp_info_t> &arp_info_vec,u32_t ip,string if_name,string &hw)
{
int pos=-1;
int count=0;
for(u32_t i=0;i<arp_info_vec.size();i++)
{
const arp_info_t & info=arp_info_vec[i];
if(info.if_name!=if_name) continue;
if(info.ip==ip)
{
count++;
pos=i;
}
}
if(count==0)
{
//mylog(log_warn,"cant find arp entry for %s %s,using 00:00:00:00:00:00\n",my_ntoa(ip),if_name.c_str());
//hw="00:00:00:00:00:00";
mylog(log_error,"cant find arp entry for %s %s\n",my_ntoa(ip),if_name.c_str());
return -1;
}
if(count>1)
{
mylog(log_error,"find multiple arp entry for %s %s\n",my_ntoa(ip),if_name.c_str());
return -1;
}
hw=arp_info_vec[pos].hw;
return 0;
}
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw)
{
ip=htonl(ip);
if(ip==htonl(inet_addr("127.0.0.1")))
{
dest_ip=ntohl(ip);
if_name="lo";
hw="00:00:00:00:00:00";
return 0;
}
string route_file;
if(read_file("/proc/net/route",route_file)!=0) return -1;
string arp_file;
if(read_file("/proc/net/arp",arp_file)!=0) return -1;
log_bare(log_debug,"/proc/net/route:<<%s>>\n",route_file.c_str());
log_bare(log_debug,"/proc/net/arp:<<%s>>\n",route_file.c_str());
auto route_vec2=string_to_vec2(route_file.c_str());
vector<route_info_t> route_info_vec;
for(u32_t i=1;i<route_vec2.size();i++)
{
log_bare(log_debug,"<size:%u>",(u32_t)route_vec2[i].size());
if(route_vec2[i].size()!=11)
{
mylog(log_error,"route coloum %d !=11 \n",int(route_vec2[i].size()));
return -1;
}
route_info_t tmp;
tmp.if_name=route_vec2[i][if_idx];
if(hex_to_u32_with_endian(route_vec2[i][dest_idx],tmp.dest)!=0) return -1;
if(hex_to_u32_with_endian(route_vec2[i][gw_idx],tmp.gw)!=0) return -1;
if(hex_to_u32_with_endian(route_vec2[i][mask_idx],tmp.mask)!=0) return -1;
if(hex_to_u32(route_vec2[i][flag_idx],tmp.flag)!=0)return -1;
route_info_vec.push_back(tmp);
for(u32_t j=0;j<route_vec2[i].size();j++)
{
log_bare(log_debug,"<%s>",route_vec2[i][j].c_str());
}
log_bare(log_debug,"%s dest:%x mask:%x gw:%x flag:%x",tmp.if_name.c_str(),tmp.dest,tmp.mask,tmp.gw,tmp.flag);
log_bare(log_debug,"\n");
}
if(find_direct_dest(route_info_vec,ip,dest_ip,if_name)!=0)
{
mylog(log_error,"find_direct_dest failed for ip %s\n",my_ntoa(ntohl(ip)));
return -1;
}
log_bare(log_debug,"========\n");
auto arp_vec2=string_to_vec2(arp_file.c_str());
vector<arp_info_t> arp_info_vec;
for(u32_t i=1;i<arp_vec2.size();i++)
{
log_bare(log_debug,"<<arp_vec2[i].size(): %d>>",(int)arp_vec2[i].size());
for(u32_t j=0;j<arp_vec2[i].size();j++)
{
log_bare(log_debug,"<%s>",arp_vec2[i][j].c_str());
}
if(arp_vec2[i].size()!=6)
{
mylog(log_error,"arp coloum %d !=11 \n",int(arp_vec2[i].size()));
return -1;
}
arp_info_t tmp;
tmp.if_name=arp_vec2[i][arp_if_idx];
tmp.hw=arp_vec2[i][arp_hw_idx];
tmp.ip=htonl(inet_addr(arp_vec2[i][arp_ip_idx].c_str()));
arp_info_vec.push_back(tmp);
log_bare(log_debug,"\n");
}
if(!interface_has_arp(if_name.c_str()))
{
mylog(log_info,"%s is a noarp interface,using 00:00:00:00:00:00\n",if_name.c_str());
hw="00:00:00:00:00:00";
}
else if(find_arp(arp_info_vec,dest_ip,if_name,hw)!=0)
{
mylog(log_error,"find_arp failed for dest_ip %s ,if_name %s\n",my_ntoa(ntohl(ip)),if_name.c_str());
return -1;
}
//printf("%s\n",hw.c_str());
dest_ip=ntohl(dest_ip);
return 0;
}
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
{

View File

@@ -86,8 +86,9 @@ int init_raw_socket();
void init_filter(int port);
void remove_filter();
int init_ifindex(char * if_name);
int init_ifindex(const char * if_name,int &index);
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen);