mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-09-15 19:54:28 +08:00
Compare commits
45 Commits
20170821.0
...
20170826.0
Author | SHA1 | Date | |
---|---|---|---|
|
57be59e070 | ||
|
fe77bb0c1a | ||
|
cb9504f904 | ||
|
dc4936dc60 | ||
|
53609c25fc | ||
|
60efcbce95 | ||
|
5c4ea515f6 | ||
|
e3b902a950 | ||
|
37f2de2ae4 | ||
|
ae497908a1 | ||
|
b59ba05422 | ||
|
cd34922722 | ||
|
51e5b023b0 | ||
|
b1800fa41a | ||
|
698ff33892 | ||
|
1293b95335 | ||
|
7e74b40977 | ||
|
d1e9bdc5da | ||
|
2b9d5c6db6 | ||
|
b86d475f1f | ||
|
0a7f9b5cc6 | ||
|
eb9633ed59 | ||
|
c0b464aeaf | ||
|
020242b73d | ||
|
2269879a2e | ||
|
057f81007d | ||
|
1f2f0d96fd | ||
|
01e0e51b9b | ||
|
6ef38709a6 | ||
|
57b874ee6d | ||
|
ab0ce3ade3 | ||
|
32f344fd3c | ||
|
968d35178a | ||
|
f8e268769c | ||
|
b9030fe81d | ||
|
e6f0ed035c | ||
|
00e1ddfecc | ||
|
15e1790f73 | ||
|
763b0b7342 | ||
|
c716d617a0 | ||
|
60393d24d8 | ||
|
9e7ed280fc | ||
|
532693edc6 | ||
|
033fa830f7 | ||
|
51464ecbfe |
52
.cproject
52
.cproject
@@ -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>
|
||||
|
68
README.md
68
README.md
@@ -1,21 +1,23 @@
|
||||
# Udp2raw-tunnel
|
||||

|
||||
|
||||
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
|
||||

|
||||
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
|
||||
|
||||
|
140
common.cpp
140
common.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
10
common.h
10
common.h
@@ -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
16
config.example
Normal 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
|
@@ -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 )
|
||||
|
@@ -2,6 +2,7 @@
|
||||

|
||||
|
||||

|
||||
|
||||
# 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
|
||||
|
||||
|
@@ -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
50
log.h
@@ -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
411
main.cpp
@@ -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)
|
||||
{
|
||||
|
44
makefile
44
makefile
@@ -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:
|
||||
|
226
network.cpp
226
network.cpp
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user