Skip to content

Instantly share code, notes, and snippets.

@parachvte
Last active August 29, 2015 14:07
Show Gist options
  • Select an option

  • Save parachvte/e68fb913a4e9291ab034 to your computer and use it in GitHub Desktop.

Select an option

Save parachvte/e68fb913a4e9291ab034 to your computer and use it in GitHub Desktop.
[Network Programming] Homework 1
1、编写一个程序判断当前系统的字节顺序。
2、请编写一个程序输出以下变量的字节表示(由低位到高位),需要给出16进制表示的输出结果。
float a = 2.3;
long b = 1;
double c = 1.0;
struct st{
int num;
char name[2];
} s;
3、请结合本课程介绍内容阐述SYN flooding攻击的原理,并提出抵御的方法?
Deadline: Oct 20, 2014
@parachvte
Copy link
Copy Markdown
Author

1、编写一个程序判断当前系统的字节顺序。

参见文章:http://vijayinterviewquestions.blogspot.com/2007/07/what-little-endian-and-big-endian-how.html

代码如下,提供一个较完整测试和一个简易的测试:

#include <stdio.h>

/*
 * Simple test
 */
bool is_big_endian() {
    int one = 1;
    return *(char *)(&one) == 0;
}

/*
 * Full test, in Big-endian, 0x00000001 is stored as 00 00 00 01
 */
bool is_big_endian2() {
    int one = 0x00000001;
    if (*((char *)(&one) + 0) != 0) return false;
    if (*((char *)(&one) + 1) != 0) return false;
    if (*((char *)(&one) + 2) != 0) return false;
    if (*((char *)(&one) + 3) != 1) return false;
    return true;
}

int main() {
    printf("The endianness of my Macbook Air is: %s\n",
            is_big_endian() ? "Big-endian" : "Little-endian");
    printf("The endianness of my Macbook Air is: %s\n",
            is_big_endian2() ? "Big-endian" : "Little-endian");

    return 0;
}

Output:

The endianness of my Macbook Air is: Little-endian
The endianness of my Macbook Air is: Little-endian

@parachvte
Copy link
Copy Markdown
Author

2、请编写一个程序输出以下变量的字节表示(由低位到高位),需要给出16进制表示的输出结果。
float a = 2.3;
long b = 1;
double c = 1.0;
struct st{
int num;
char name[2];
} s;

#include <stdio.h>

#define IS_BIG_ENDIAN is_big_endian()

bool is_big_endian() {
    int one = 1;
    return *(char *)(&one) == 0;
}

void pltoh(void *num, int size) {
    int i;
    if (IS_BIG_ENDIAN)
        for (i = size - 1; i >= 0; i--)
            printf("%02x ", *((unsigned char *)(num) + i));
    else
        for (i = 0; i < size; i++)
            printf("%02x ", *((unsigned char *)(num) + i));
    printf("\n");
}

float a = 2.3;
long b = 1;
double c = 1.0;
struct st {
    int num;
    char name[2];
} s;

int main() {
    pltoh(&a, sizeof(float));
    pltoh(&b, sizeof(long));
    pltoh(&c, sizeof(double));
    pltoh(&s, sizeof(struct st));
    return 0;
}

Output:

33 33 13 40
01 00 00 00 00 00 00 00
00 00 00 00 00 00 f0 3f
00 00 00 00 00 00 00 00

@parachvte
Copy link
Copy Markdown
Author

3、请结合本课程介绍内容阐述SYN flooding攻击的原理,并提出抵御的方法?

SYN flooding是最常见的DoS/DDoS攻击,主要利用了TCP三次握手的设计/缺陷:

『背景知识1』通常listen() system call的函数是这样的:int listen(int socket, int backlog);,该函数告诉Kernel我们要在socket这个socket descriptor监听连接。
『背景知识2』TCP三次握手流程:客户端发送SYN请求,服务端发送SYN/ACK应答,然后客户端再发送ACK,数据传送开始。
『背景知识3』在三次握手完成、数据传送之前(在编程上来讲是accept()被调用之前),需要有个地方来保存这些或者处于「SYN Received」状态或者处于「ESTABLISHED」状态的连接,这个地方就是backlog queue,而上面listen()函数里的参数backlog就是指这个queue的大小。关于backlog可以看看这篇文章,通过查查文档也可以知道在Unix上,backlog的最大取值是128。

『攻击原理』攻击者使用肉机往攻击目标的主机发送大量SYN请求,之后会收到目标主机的SYN/ACK应答,这时候肉机不再往目标主机发ACK。那么目标主机的backlog queue一会儿就会填满了各种「SYN Received」状态的连接,没有办法再接受新的连接,out of service了。

『抵御方法』常见抵御方法:

  • 过滤,把具有攻击性的IP给过滤掉
  • 增大backlog,但是也只能增大到128,同时backlog大的时候效率极其低下,不建议这么做
  • 减小「SYN Received」的Timer,一旦超时即把连接扔掉
  • 复用老的TCB(Transmission Control Block),有一些协议栈的实现允许把最老(创建最久)的TCB覆盖掉。该实现的假设前提是:「ESTABLISHED」的连接在backlog满之前就抖会被accept()掉。所以当backlog很小,或者攻击速度足够快的时候,该方法很容易爆掉。
  • SYN Cache,不给非「ESTABLISHED」的连接分配TCB了,通过TCP包的IP+port+secret bits计算一个hash出来,存到一个hash table里面,对于每个hash值都是个桶,桶的容量满了就把最老的请求扔掉;如果收到ACK,而且可以在hash table中找到值,一个连接的状态才改变成「ESTABLISHED」。该方法相当于拿一部分的CPU时间来换空间,是个不错的方法。
  • SYN Cookies,该方法做得比SYN Cache更绝一点,不存hash值了,算出来的hash当做SYN/ACK中的SYN的值,发给客户端,如果客户端是个正常的用户,那么就可以从收到的ACK包里还原之前的连接状态。缺点就是,必须抛弃使用TCP options。
  • Firewalls and Proxies,由防火墙来接收请求,完成三次握手,当连接「ESTABLIESH」之后再把它们传递给服务器。

参考资料:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment