Writing to VpnService output stream provides no response - android

My application implements VpnService to intercept network traffic and provide tailored responses. The goal is to handle traffic to specific addresses, and discard other requests.
Presently I'm successful in parsing incoming requests and constructing and sending responses. The problem, however, is that these responses do not arrive as the actual response to the original request; testing with a socket connection simply times out.
In order to make this distinction, I'm presently parsing the raw IP packets from the VpnService's input stream as follows:
VpnService.Builder b = new VpnService.Builder();
b.addAddress("10.2.3.4", 28);
b.addRoute("0.0.0.0", 0);
b.setMtu(1500);
...
ParcelFileDescriptor vpnInterface = b.establish();
final FileInputStream in = new FileInputStream(
vpnInterface.getFileDescriptor());
final FileOutputStream out = new FileOutputStream(
vpnInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
try {
while (vpnInterface != null && vpnInterface.getFileDescriptor() != null
&& vpnInterface.getFileDescriptor().valid()) {
packet.clear();
SystemClock.sleep(10);
// Read the outgoing packet from the input stream.
final byte[] data = packet.array();
int length = in.read(data);
if (length > 0) {
packet.limit(length);
/*
1. Parse the TCP/UDP header
2. Create an own socket with the same src/dest port/ip
3. Use protect() on this socket so it not routed over tun0
4. Send the packet body (excluding the header)
5. Obtain the response
6. Add the TCP header to the response and forward it
*/
final IpDatagram ip = IpDatagram.create(packet);
...
}
}
IpDatagram is a class through which create() parses the byte array into a representation of the IP packet, containing the IP header, options and body. I proceed to parse the byte array of the body according to the protocol type. In this case, I'm only interested in IPv4 with a TCP payload—here too I create a representation of the TCP header, options and body.
After obtaining an instance of IpDatagram, I can determine the source and destination IP (from the IP header) and port (from the TCP header). I also acknowledge the request TCP's flags (such as SYN, ACK and PSH) and sequence number. In the app:
Subsequently I construct a new IpDatagram as a response, where:
The source and destination IP are reversed from the incoming request;
The source and destination ports are reversed from the incoming request;
The TCP acknowledgement number is set to the incoming request's sequence number;
A dummy HTTP/1.1 payload is provided as the TCP's body.
I convert the resulting IpDatagram to a byte array and write it to the VpnServer's output stream:
TcpDatagram tcp = new TcpDatagram(tcpHeader, tcpOptions, tcpBody);
IpDatagram ip = new Ip4Datagram(ipHeader, ipOptions, tcp);
out.write(ip.toBytes());
My application displays the outgoing datagram as it should be, but nevertheless, all connections are still timing out.
Here's a sample incoming TCP/IP packet in hexadecimal:
4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b00000000a00239089a570000020405b40402080a00bfb8cb0000000001030306
And the resulting outgoing TCP/IP packet in hexadecimal:
450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421
However, a simple test simply times out; I creata a new socket and connect it to the IP above, yet the response provided above never arrives.
What could be going wrong? Is there any way to troubleshoot why my response isn't arriving?

This TCP/IP response doesn't contain a valid TCP header checksum:
450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421
More generally, the request and response mechanism is very picky. This is of course the case due to the very nature of networking, and as the kernel takes care of ensuring that responses are good and to which port a response should be sent, anything that doesn't compute will simply be discarded as a bad packet. This also holds true when responding from the VpnService's output stream, as you're operating on the network layer.
To return to the specific case above: the IP packet is correct (including the checksum) but the TCP packet was not. You need to compute the TCP header checksum over not just the TCP packet, but prefixed by the pseudo header as follows:
(source: tcpipguide.com)
It should be then be computed over the following bytes:

Related

How can I measure the transmission time between two android devices?

I would like to monitor Wifi-Direct network (Bandwidth, latency etc). How can I measure the time it takes for X bytes to be received over a network (wifi direct). I mean TX + over the network + RX time.
In DMMS (android Studio)I found the option of Network Statistics but here it is only shown transmission and reception time (and it is not very accurate because it appears on a graph).
I had thought about using System.currentTimeMillis() but I have not found how to synchronize the clocks of both devices.
TX:
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
int tamMensaje= 1024*1024; // 1 MB
byte[] bitAleatorio = new byte [tamMensaje]; // 1 byte [-128 a 127
for (int x=0;x<bitAleatorio.length;x++){
bitAleatorio[x] =(byte) Math.round(Math.random());
}
DataOutputStream DOS = new DataOutputStream(socket.getOutputStream());
for(int i=0;i<1024;i++){
DOS.write(bitAleatorio,(i*1024),1024);
}
RX:
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
Socket client = serverSocket.accept();
DataInputStream DIS = new DataInputStream(client.getInputStream());
int tamMensaje= 1024*1024;
byte[] msg_received2= new byte [tamMensaje];
for(int i=0;i<1024;i++){
DIS.read(msg_received2,(i*1024),1024);
}
client.close();
serverSocket.close();
Thanks
There are two approaches that can considerably accurate solve the problem:
Sync time on both devices.
You can use NTP for that and either install a separate app like this one or implement it in your code using a library like this one.
After that you can rely on System.currentTimeMillis() to compare the message sent/receive time on both devices.
Using relative time or time of single device.
You can implement something like icmp echo, using udp datagrams (they are faster than tcp). The algorithm should be following (assuming we have devices A and B):
A sends some packet to B and saves timeSent somewhere;
B receives packet and immediately sends ACK packet to A;
A receives ACK and saves timeRecv;
Finally, Long latency = (timeSent - timeRecv)/2;.
This will work for small payloads, like icmp echo. Measuring large network transmission time can be done by sending separate ACK responses for both start/end of receiving it.

Android nfcA.connect(), nfcA.transceive(), nfcA.setTimeout() and nfcA.getMaxTransceiveLength()

I have a a number of newbie NfcA questions. There seems to be little guidance on this in the docs and elsewhere on the web, so I hope no-one minds me stringing a few basic questions together here...
I am using nfcA.transceive() to write data to my NTAG213 tag like this:
byte[] result = nfcA.transceive(new byte[] {
(byte)0xA2, // WRITE
(byte)(pageNum & 0x0ff),
myData[0], myData[1], myData[2], myData[3]
});
1. The result array is a single byte of value 10. What does this mean and what other values should I look out for?
I am also using the same method to read data from my NTAG213 tags:
byte[] result = nfcA.transceive(new byte[] {
(byte)0x30, // READ
(byte)(pageNum & 0x0ff)
});
2. I expected this to return 4 bytes of user data (i.e., the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so? (I ask as I have seen code examples from reputable sources of both.)
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
1. The result array for a WRITE command is a single byte of value 10. What does this mean and what other values should I look out for?
The value 10 (Ah in hexadecimal or 1010b in binary representation) is an explicit ACK, an acknowledgement returned when a command that returns no data succeeds.
The possible values are actual data, ACK, passive ACK, or NACK. These are defined by the NFC Forum Digital Protocol specification and by the NFC Forum Type 2 Tag Operation specification.
If the command is expected to return actual data on success, the data is returned instead of an explicit ACK value.
ACK is defined as a 4-bit short frame (see NFC Forum Digital Protocol specification and ISO/IEC 14443-3 for further details) with the value 1010b (Ah).
A passive ACK is defined as the tag not sending a response at all within a certain timeout.
NACK is defined as a 4-bit short frame with the value 0x0xb (where x is either 0 or 1).
The NTAG213/215/216 product data sheet is a bit more specific on possible NACK values:
0000b (0h) indicates an invalid command argument.
0001b (1h) indicates a parity or CRC error.
0100b (4h) indicates an invalid authentication counter overflow.
0101b (5h) indicates an EEPROM write error.
In addition to the above, the NFC stack implementations on some devices do not properly propagate NACK responses to the app. Instead they either throw a TagLostException or return null. Similarly, you might(?) get a TagLostException indicating a passive ACK.
Thus, you would typically check the result of the transceive method for the following (unless you send a command that is expected to result in a passive ACK):
try {
response = nfca.transceive(command);
if (response == null) {
// either communication to the tag was lost or a NACK was received
} else if ((response.length == 1) && ((response[0] & 0x00A) != 0x00A)) {
// NACK response according to Digital Protocol/T2TOP
} else {
// success: response contains ACK or actual data
}
} catch (TagLostException e) {
// either communication to the tag was lost or a NACK was received
}
2. I expected the READ method to to return 4 bytes of user data (i.e. the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
The READ command is defined to return 4 blocks of data starting with the specified block number (in the NFC Forum Type 2 Tag Operation specification). Thus, if you send a READ command for block 4, you get the data of blocks 4, 5, 6, and 7.
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so?
If you receive the Tag handle directly from the NFC system service (through an NFC intent) the tag won't be connected. So unless you use the Tag handle before calling nfca.connect(), I don't see why you would want to call nfca.isConnected() before. However, calling that method before connecting has barely any performance overhead since calling isConnected() on a closed tag technology object will be handled by the famework API without calling into the NFC system service. Hence, it's not much more overhead than a simple if over a boolean member variable of the NfcA object.
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
I'm not sure about that one. However, the transceive timeout is typically reset on disconnecting the tag technology.
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
No, you can only write one block at a time. This is limited by the WRITE command of the NTAG213, which only supports one block as data input.
However, a transceive buffer size of 253 allows you to use the FAST_READ command to read multiple blocks (up to 62, so up to 45 for the NTAG213) at a time:
int firstBlockNum = 0;
int lastBlockNum = 42;
byte[] result = nfcA.transceive(new byte[] {
(byte)0x3A, // FAST_READ
(byte)(firstBlockNum & 0x0ff),
(byte)(lastBlockNum & 0x0ff),
});

Bluetooth - Output Stream

I have connected an arduino with my android device and I have set up the connection and obtained Output Stream.
ANDROID PART
String one = "1";
byte[] input = one.getBytes(Charset.forName("UTF-8"));
mConnectedThread.write(input);
ARDUINO PART
How can I process the received byte[] and convert it back to String?
There is a 128byte buffer on the incoming stream. Use
In your loop():
char inByte;
// check for bytes in the buffer
if (Serial.available() > 0) {
// read the available bytes one at a
// time and purge from buffer
inByte = Serial.read();
// print out byte so you can see it on
// the serial monitor
Serial.print(inByte);
}
If the buffer is big enough for your needs then you won't need to worry about coding anything else. You can deal with the incoming bytes in a char array or read the individual chars into a String object.
There is lots of good information here:
http://arduino.cc/en/Reference/string
...on char arrays and a link at the top of that page to the String object. Let me know if you have further questions, hopefully this gets you at least started and debugging the incoming code correctly

android TrafficStats getUidRxBytes inaccurate

I write a little android app, sends Http request, receives response from server, and count how many bytes transmitted and received.
and the code is simply as follow
long receivedBytes = TrafficStats.getUidRxBytes(uid)-lastNumer
i find that the receivedBytes is always larger the size http Header+http Body, for example
the actual http frame's size i caught( use wireshark) in server is 1645 bytes(header+body), but the android API returns receivedBytes is 1912, so as the transmission.
the TrafficStats getUidRxBytes itself is inaccurate(may be this problem is specific to my platform samsung i9300 with cynogenmod 10.3)
finally, i find the correct way to count the data usage i find other way to count the data usage which seems more accurate than TrafficStats API.(many thanks to here)
private long[] getStat() {
String line, line2;
long[] stats = new long[2];
try {
File fileSnd = new File("/proc/uid_stat/"+uid+"/tcp_snd");
File fileRcv = new File ("/proc/uid_stat/"+uid+"/tcp_rcv");
BufferedReader br1 = new BufferedReader(new FileReader(fileSnd));
BufferedReader br2 = new BufferedReader(new FileReader(fileRcv));
while ((line = br1.readLine()) != null&& (line2 = br2.readLine()) != null) {
stats[0] = Long.parseLong(line);
stats[1] = Long.parseLong(line2);
}
br1.close();
br2.close();
} catch (Exception e) {
e.printStackTrace();
}
return stats;
}
I see that you've already found a solution, but I'll add my thoughts on your question as it might be useful to other people (ended up here myself after googling how to use the TrafficStats API).
The API documentation states:
Statistics are measured at the network layer, so they include both TCP and UDP usage.
The documentation could indeed be more thorough, but I'm inclined to say that one can assume that the returned byte count also includes the bytes making up the transport layer header and the network layer header.
HTTP is an application layer protocol. When you're calculating your expected bytes to be the HTTP header bytes plus the HTTP body bytes, you're only dealing with application layer bytes, hence not accounting for transport and network layer header bytes. I assume TCP is used for the download. This adds a header ranging from 20 to 60 bytes. Moreover, let's assume you're using IPv4 for the download. This also adds a header ranging from 20 to 60 bytes.
Obviously this won't account for the entire 1912 - 1645 = 267 bytes, but it might give you/other people some leads.
A bit off-topic, but still related. It's not quite clear if the TrafficStats API actually count header bytes or not. According to this answer, the API does not count header bytes. However, given the API documentation listed above, the linked answer may be stipulating something that is not true (at least not for API level 21). Moreover, this question also hints at TrafficStats actually counting network and transport layer header bytes (check comments).
TrafficStats actually counts network and transport layer header bytes. See kernel source and TrafficStatsTest.
From my understanding, you should combine getUidRxBytes with getUidRxPackets.
You should have something like : getUidRxBytes = getUidRxPackets * (tcp/ip header size)

Hang-up on TCP socket send call in Android native code

I have a problem with socket send (or write) function on android.
There is my network lib that I use on Linux and Android. Code is written in C.
On Android, application creates a service, which loads a native code and creates the connection with the help of my network lib. Connection is the TCP socket. When I call send (or write, no difference), code hangs in this call in most cases. Sometimes, it unhangs after 10-120 seconds. Sometimes, it waits longer (until I kill the application). Data size being sent is about 40-50 bytes. First data sending (handshake, 5 bytes) never hangs (or I am just lucky). The hanging send is, usually, next after handshake packet. Time between this first handshake packet sending and hanging sending is about 10-20 seconds.
The socket is used on another thread (I use pthread), where the recv is called. But, I do not send data to Android in this time, so recv is just waiting when I call send.
I am sure that other side is waiting for the data – I see that recv on other side returns with EAGAIN every 3 seconds (I set timeout) and immediately calls recv again. Recv is waiting 10 bytes always (minimal size of packet).
I am unable to reproduce this behavior on Linux-to-Android transfer or Linux-to-Linux, only on Adnroid-to-Linux. I am able to reproduce this with two available to me different Android devices, so I don’t think this is the problem in broken hardware of one particular device.
I tried to set SO_KEEPALIVE and TCP_NODELAY options with no success.
What can issue the hang-up on send/write calls and how can I resolve this?
Socket created with this code:
int sockfd, n;
addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
{ /* stripped error handling*/ }
ressave = res;
do
{
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) continue;
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
{
break; /* success */
}
close(sockfd); /* ignore this one */
} while ((res = res->ai_next) != NULL);
Hanging send operation is:
mWriteMutex.lock();
mSocketMutex.lockRead();
ssize_t n = send(mSocket, pArray, size, 0);
mSocketMutex.unlock();
mWriteMutex.unlock();
The problem is solved with the help of Nikolai N Fetissov in commentaries - his right question has unblocked my mind and I found a problem in RWMutex.

Categories

Resources