Sending message from udp client to udp server without sending protocol address of client - udp

I have a query is it possible to send data from udp client to udp server without sending the protocol address and then from server to client
Server.c
if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
printf("Couldn't bind to the port\n");
return -1;
}
printf("Done with binding\n");
printf("Listening for incoming messages...\n\n");
// Receive client's message:
if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
(struct sockaddr*)NULL, NULL) < 0){
printf("Couldn't receive\n");
return -1;
}
// printf("Received message from IP: %s and port: %i\n",
// inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("Msg from client: %s\n", client_message);
// Respond to client:
int n = atoi(client_message);
int m =0, sum = 0;
while(n>0){
m=n%10;
sum=sum+m;
n=n/10;
}
sprintf(server_message, "%d", sum);
if (sendto(socket_desc, server_message, strlen(server_message), 0,
(struct sockaddr*)&client_addr, client_struct_length) < 0){
printf("Can't send\n");
return -1;
}
When I send data from client to server the server printed what I had sent from client but then then when I tried to send data back to client it is unable to send the modified data.

client_addr does not magically get filled with the clients address. It has to be explicitly done in recvfrom - but you use instead NULL there and thus throw away this information:
if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
(struct sockaddr*)NULL, NULL) < 0){

Related

How get session key from ssl session

I created client and server program to exchange the data.
Client and server uses tls to pass the message securely.
Used openssl to make the connection between server and client.
Now i have the ssl handle.
Is there any way to extract server write key, server random, client random,client write key, master key.
in the below code sample Servlet method will connect to the client do the handshake get the session keys.
i am trying to read the tls packet from the port after tls handshake completed and pass the packet to another module.
To check the for malformed or invalid packets i need to decrypt the packet to inspect the payload where i required the session keys.
Is there any way to extract server write key, server random, client random,client write key, master key.
code snippet:
main(){
// Initialize the SSL library
SSL_library_init();
portnum = Argc[1];
ctx = InitServerCTX(); /* initialize SSL */
LoadCertificates(ctx, "mycert.pem", "mycert.pem"); /* load certs */
server = OpenListener(atoi(portnum)); /* create server socket */
while (1)
{ struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(server, (struct sockaddr*)&addr, &len); /* accept connection as usual */
printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
Servlet()
{
if ( SSL_accept(ssl) == FAIL ) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else
{
unsigned char key[100];
//SSL_SESSION_get_master_key(ssl,key,100);
//printf("masterkey:%s", key);
ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
printf("Client msg: \"%s\"\n", buf);
if ( bytes > 0 )
{
if(strcmp(cpValidMessage,buf) == 0)
{
SSL_write(ssl, ServerResponse, strlen(ServerResponse)); /*
send reply */
}

Sending and receiving UDP using the same port does not work with the asio library?

I'm trying to send and receive UDP packets through the same endpoint. As far as I know this should be possible. But I can not get it to work with the asio library (version 1.20.0).
This is what I do:
asio::io_context io_context;
asio::ip::udp::socket* udpSendRecvSocket = new asio::ip::udp::socket(io_context, asio::ip::udp::endpoint(asio::ip::udp::v4(), 7782));
asio::error_code ec;
char data[1000];
//
// send packet
//
std::string ipAddress = "127.0.0.1";
asio::ip::address ip_address = asio::ip::address::from_string(ipAddress);
asio::ip::udp::endpoint remoteTarget_endpoint(ip_address, 5500);
udpSendRecvSocket->send_to(asio::buffer(data, 50), remoteTarget_endpoint, 0, ec);
if (ec) {
return 0;
}
//
// receive packets
//
size_t avLen = udpSendRecvSocket->available(ec);
while (avLen) {
asio::ip::udp::endpoint remote_endpoint;
size_t length = udpSendRecvSocket->receive_from(asio::buffer(data, 1000), remote_endpoint, 0, ec);
int p = remote_endpoint.port();
if (ec) {
return 0;
}
avLen -= length;
}
The receive does not work correctly. I do receive a packet that I send (from some other app). I know because avLen gets the right value. But when executing the receive_from(), if fails. And the port number in p gets the value 5500. This is the value of the target port of the send_to() call that was executed before.
The strange thing is that when I remove the send_to() call, the receive does work correctly and the p will reflect the correct port number of the sending application.
Is this a bug?

Apache actively close tcp connections when keep-alive is set by the client

I'm trying to do Apache performance benchmarking for my course project. But I meet a strange problem. When I use a single client to establish multiple TCP connections (e.g. 100) to an Apache server and send HTTP 1.1 requests with the Connection: keep-alive header, I suppose the TCP connections can be reused. But the Apache server will actively terminate TCP connections, even if Connection: Keep-Alive and Keep-Alive: xxx are included in the HTTP response header.
this is my client code (I obfuscate the IP address):
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <sys/time.h>
#define DEBUG
#define MAX_SOCKETS_NUM 100
#define BUF_LEN 4096
int main() {
int i;
struct sockaddr_in server_addr, peer_addr;
int res, len = sizeof(peer_addr);
char *req = "GET /20KB HTTP/1.1\r\n"
"Host: x.x.x.192\r\n"
"Connection: keep-alive\r\n"
"Upgrade-Insecure-Requests: 1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Language: zh-CN,zh;q=0.9\r\n"
"\r\n";
char buf[BUF_LEN + 1];
int sockets[MAX_SOCKETS_NUM];
int estb_num = 0;
int estb_map[MAX_SOCKETS_NUM];
struct timeval goal, now, interval;
// create sockets
for (i = 0; i < MAX_SOCKETS_NUM; i++) {
if ((sockets[i] = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0) {
printf("Socket %d error!\n", i);
return -1;
}
}
// initialize server_addr
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
if (inet_pton(AF_INET, "x.x.x.192", &server_addr.sin_addr) <= 0) {
printf("Invalid address/Address not supported\n");
return -1;
}
// connect to the victim server
for (i = 0; i < MAX_SOCKETS_NUM; i++) {
if ((res = connect(sockets[i], (struct sockaddr *)&server_addr, sizeof(server_addr))) == 0) {
#ifdef DEBUG
printf("Socket %d connected immediately.\n", i);
#endif
estb_map[i] = 1;
estb_num++;
}
else if (res == -1) {
if (errno != EINPROGRESS) {
printf("Error occured when connect() is called on socket %d.\n", i);
return -1;
}
#ifdef DEBUG
printf("Socket %d sends SYN packet but the ACK is not received.\n", i);
#endif
}
}
while (1) {
if (estb_num == MAX_SOCKETS_NUM)
break;
for (i = 0; i < MAX_SOCKETS_NUM; i++) {
while (1) {
res = getpeername(sockets[i], (struct sockaddr *)&peer_addr, &len);
if (res == 0) {
estb_num++;
#ifdef DEBUG
printf("Socket %d connects successfully.\n", i);
#endif
break;
}
}
}
}
interval = (struct timeval) {
.tv_sec = 1,
.tv_usec = 0
};
len = strlen(req);
while (1) {
gettimeofday(&now, NULL);
timeradd(&now, &interval, &goal);
#ifdef DEBUG
printf("%ld.%ld\n", goal.tv_sec, goal.tv_usec);
#endif
// send requests
for (i = 0; i < MAX_SOCKETS_NUM; i++) {
res = send(sockets[i], req, len, 0);
if (res == -1) {
printf("socket:%ld errno:%ld\n", i, errno);
}
}
while (1) {
for (i = 0; i < MAX_SOCKETS_NUM; i++) {
res = recv(sockets[i], buf, BUF_LEN, 0);
if (res == 0) {
struct sockaddr_in dbg_addr;
int dgb_addr_len = sizeof(struct sockaddr_in);
getsockname(sockets[i], &dbg_addr, &dgb_addr_len);
printf("socket:%d port:%d\n", i, ntohs(dbg_addr.sin_port));
goto end;
}
else if (res == -1) {
if (errno != EAGAIN)
printf("Error occurs when recv is called.\n");
}
else {
// do nothing because we don't need the response
}
}
gettimeofday(&now, NULL);
if (timercmp(&now, &goal, >) != 0) {
#ifdef DEBUG
printf("%d.%d\n", now.tv_sec, now.tv_usec);
#endif
break;
}
}
}
end:
return 0;
}
the workflow of the client (with the IP address x.x.x.198) is:
establish 100 tcp connections to the server (with the IP address x.x.x.192) using non-blocking socket.
send the same requests on the 100 tcp connections
invoking non-blocking recv repeatedly on these 100 sockets for 1 second
goto 2.
one execution of the program generates the following output:
Socket 0 sends SYN packet but the ACK is not received.
(some lines are omitted)
Socket 99 sends SYN packet but the ACK is not received.
Socket 0 connects successfully.
(some lines are omitted)
Socket 99 connects successfully.
1639450192.343129
1639450192.343155
1639450193.343163
socket:63 port:56804
The output indicates in the second round of requests (the first round is finished because it prints two timestamps, but the second round only prints one), the recv function on the 63th socket with the local port number 56804 returns 0, which means the Apache server actively terminates tcp connections. And I dumped all the packets on the client using tcpdump, the following figure shows the packet trace of the connection with the local port number 56804:
the packet trace shows the same result that the server actively sends tcp FIN packet to the client to terminate the TCP connection. But we can see Connection: Keep-Alive and Keep-Alive: timeout=10m, max=1999 are included in the response header which means the Apache server handles keep-alive correctly.
The server runs Ubuntu 20.04.3 and Apache 2.4.41.
I's very confused about why this happens, why will Apache close keep-alive connections? I'd be appreciate if you can help me, thanks!
From this document:
A host MAY keep an idle connection open for longer than the time that
it indicates, but it SHOULD attempt to retain a connection for at
least as long as indicated.
Capital letters there are key, and written like this in the document:
Your case matches the "SHOULD" part. E.g. keep-alive is a recommendation - but if the server needs those resources (or is configured to have less open connections than the number of your clients) it's free to close them at will. Your clients will need to deal with this state.
If the described behavior is dependent on the number of parallel sockets that you open (apart from the timeout), you're most likely running into resource limits on your server - either explicitly configured, or implicit, from default values.
Imagine how easy a DDOS attack would be if all that's required was a couple of keep-alive requests to saturate the number of concurrent connections that the server offers.
Also note that timeout is based on different perceptions of time on server (starting with sending the last packet) and client (starting when receiving the last packet)

Mina transmission frequency is too fast, causing received packets are merged

I'm using Apache Mina framework for communication between server and client, when I test the programe, I found if my transmission frequency is too fast, the received packets will merge to a big one, which should be each separate package.
My client used to send message, code like below:
public static void main(String[] args) {
// IoConnector instance
IoConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(3000); // 连接超时时间
// configure filters
// connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter(
// new TextLineCodecFactory(Charset.forName("UTF-8"))));
DefaultIoFilterChainBuilder builder = (DefaultIoFilterChainBuilder) connector.getFilterChainBuilder();
Map<String, IoFilter> filters = new LinkedHashMap<>();
filters.put("protocolCodecFilter", new ProtocolCodecFilter(new TcpCodecFactory()));
filters.put("executor", new ExecutorFilter());
filters.put("loggingFilter", new LoggingFilter());
builder.setFilters(filters);
connector.setFilterChainBuilder(builder);
// set handler
connector.setHandler(new TcpServerHandler());
// connect to the server
ConnectFuture future = connector.connect(new InetSocketAddress(address, port));
future.awaitUninterruptibly(); // waiting for connection
IoSession session = future.getSession();
byte[] data = new byte[10];
for (int i = 0; i < 100; ++i) {
data[0] = (byte)i; // first byte means the message sequence number
for (int j = 1; j < 10; ++j) {
data[j] = (byte) (j + 10);
}
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
session.write(data);
}
session.getCloseFuture().awaitUninterruptibly(); // wait for close
connector.dispose();
}
When I comment the sleep code, which means I send message frequently, My received message will like below:
The message sequence number is 0, 1, 6..., If I uncomment the sleep code, the message sequence number is 0, 1, 2, 3...
What's the difference? How to avoid the mixed packets in fast transmission?
You are using a TCP socket which is a stream channel versus UDP which is a message channel. Your messages are being combined because that is how TCP works on all platforms to effectively create as few network packets as possible.
Unless the messages are out of order, then this is the expected behavior.

Broken Pipe signal on a DNS client

I'm building a DNS client. A child process handles the request through an UDP socket, while the parent handles the reply. I need the parent to know how many bytes were sent, in order to print the URLs. I tried the following approach with pipe()
childPID = fork();
pipe(fd);
if(childPID == 0){
close(fd[0]);
sent_bytes = sendDNS(sock_udp, &serverAddr, argv[2]);
memcpy(in_buf, &sent_bytes, sizeof(sent_bytes));
write(fd[1], in_buf, sizeof(sent_bytes));
exit(0);
}
else{
close(fd[1]);
int inBytes = -1;
struct sockaddr reply_addr;
n = sizeof(reply_addr);
while(inBytes < 0){
inBytes = recvfrom(sock_udp, buffer, DNS_MAX_RESPONSE, 0, &reply_addr, (socklen_t*)&n);
read(fd[0], out_buf, sizeof(sent_bytes));
memcpy(pipe_msg, out_buf, sizeof(sent_bytes));
printDNSmsg((struct dnsReply*)buffer);
}
}
But GDB shows a SIGPIPE received on the child process. What am I missing?
How would you print a DNS reply (variable length buffer)?
You need to call pipe() before fork(), of course. But you're not actually using the information anywhere. Why do you care how many bytes were sent, as long as you got a reply? And why would you do a UDP send in a separate thread, let alone a separate process? It all seems completely pointless.