{"id":31892116,"url":"https://github.com/li1553770945/synscan","last_synced_at":"2025-10-13T08:29:50.051Z","repository":{"id":158333338,"uuid":"500503145","full_name":"li1553770945/SYNScan","owner":"li1553770945","description":"SYN scanner","archived":false,"fork":false,"pushed_at":"2022-06-07T00:54:26.000Z","size":8,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-10T14:41:37.802Z","etag":null,"topics":["handshake","tcp"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/li1553770945.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-06T16:09:08.000Z","updated_at":"2024-08-14T06:11:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"2096166e-c390-4a56-8f72-917b63b9347b","html_url":"https://github.com/li1553770945/SYNScan","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/li1553770945/SYNScan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/li1553770945%2FSYNScan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/li1553770945%2FSYNScan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/li1553770945%2FSYNScan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/li1553770945%2FSYNScan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/li1553770945","download_url":"https://codeload.github.com/li1553770945/SYNScan/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/li1553770945%2FSYNScan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279014325,"owners_count":26085492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["handshake","tcp"],"created_at":"2025-10-13T08:29:47.474Z","updated_at":"2025-10-13T08:29:50.043Z","avatar_url":"https://github.com/li1553770945.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SYNScan\n计网实验要求我们实现一个端口扫描器，可以扫描指定IP段的指定端口，写的过程中遇到了一些问题，在此记录一下。\n\n\n## 端口扫描的三种方式\n\nTCP端口扫描有三种方法：\n\n1. 全TCP连接，这种方法使用三次握手与目标主机建立标准的tcp连接。但是这种方法跟容易被发现，被目标主机记录，而且效率较低。\n   \n2. SYN扫描，扫描主机自动向目标主机的指定端口发送SYN数据段，表示发送建立连接请求。如果目标主机的回应报文SYN=1，ACK=1.则说明该端口是活动的，接着扫描主机发送回一个RST给目标主机拒绝连接。导致三次握手失败。如果目标主机回应是RST则端口是“死的”。\n   \n3. FIN扫描，发送一个FIN=1的报文到一个关闭的窗口该报文将丢失并返回一个RST，如果该FIN报文发送到活动窗口则报文丢失，不会有任何反应。缺点是在部分OS上，表现可能不一样。\n\n综合考虑，我最终使用了第二种方法。\n\n## 介绍\n\n+ 运行环境：ubuntu 20.04验证正常，wsl1会失败\n\n## 使用方法\n\n修改main.cpp中的\n\n```cpp\nstring my_ip = \"192.168.1.116\";\nstring des_host = \"192.168.1.1\";\nint mask = 24;\nint min_port = 80;\nint max_port = 8000;\n```\n如果需要扫描ip范围，则main中调用ScanRange(),如果要扫描特定ip，则main中调用ScanOneIp()。\n\n然后直接运行build.sh,会自动编译并运行，需要输入一次密码。\n\n## 步骤\n\n### 创建socket\n\n```cpp\nint sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);\nint on = 1; \nint opt =  setsockopt(sock,IPPROTO_IP,IP_HDRINCL,\u0026on,sizeof(on));\nif(sock \u003c 0)\n{\n  cout\u003c\u003c\"sock:\"\u003c\u003csock\u003c\u003c\" errno:\"\u003c\u003cerrno\u003c\u003c\" desc:\"\u003c\u003cstrerror(errno)\u003c\u003cendl;\n  return;\n}\n```\n\n让我没想到的是，创建socket就成了我的第一个问题。有的人说应该用IPPROTO_TCP，有的人说应该用IPPROTO_RAW。最后经过测试发现，这个与平台有关，在windows上不支持SOCK_RAW, IPPROTO_TCP这样的组合方式。后面的setsockopt是为了让OS不要自动填充ip头。\n\n\n\n### 发送\n\n```cpp\n\nstatic int  seq = 1;\nsockaddr_in dst_ip = { 0 };\nmemset(\u0026dst_ip,0,sizeof(dst_ip));\ndst_ip.sin_family = AF_INET;\ndst_ip.sin_addr.s_addr = inet_addr(IpToString(ip).data());\ndst_ip.sin_port = htons(port);\n\nint re = sendto(\n    sock,\n    buffer,\n    sizeof(buffer),\n    0,\n    (sockaddr*)\u0026dst_ip,\n    sizeof(dst_ip)\n);\n\n```\n发送和接收的代码都想对简单，这里不是完整代码，完整代码请见我的github。\n\n\n### 接收\n\n```cpp\n while(recving)\n  { \n    int re = recvfrom(sock, (char*)buffer, sizeof(buffer), 0,\n    \u0026addr, (socklen_t*)\u0026size);\n    if(ip_ptr-\u003eip_dst.s_addr != inet_addr(my_ip))//不是发给自己的或者是127.0.0.1\n    {\n        continue;\n    }\n    if(ips.find(htonl(ip_ptr-\u003eip_src.s_addr)) == ips.end())//不是要ping的ip\n    {\n        continue;\n    }\n    \n    if(tcp_ptr-\u003esyn\u0026\u0026tcp_ptr-\u003eack)\n    {\n        //cout\u003c\u003cIpToString(htonl(ip_ptr-\u003eip_src.s_addr))\u003c\u003c\":\"\u003c\u003chtons(tcp_ptr-\u003esource)\u003c\u003c\"-\u003e\"\u003c\u003cIpToString(htonl(ip_ptr-\u003eip_dst.s_addr))\u003c\u003c\":\"\u003c\u003chtons(tcp_ptr-\u003edest)\u003c\u003cendl;\n        //cout\u003c\u003c\"tcp.syn:\"\u003c\u003ctcp_ptr-\u003esyn\u003c\u003c\" tcp.ack:\"\u003c\u003ctcp_ptr-\u003eack\u003c\u003c\" tcp.rst:\"\u003c\u003ctcp_ptr-\u003erst\u003c\u003cendl;\n        mtx.lock();\n        result[htonl(ip_ptr-\u003eip_src.s_addr)].insert(htons(tcp_ptr-\u003esource));\n        mtx.unlock();\n    }\n    // sleep(5);\n}\n```\n\n由于接收是同步操作，而且recvfrom会把所有的符合条件的包都接收，不针对特定ip，因此我们只需要全局开一个接收线程即可。\n\n## 遇到的问题\n\n### wsl1下无法发送数据\n\n这个问题很坑，我用的ubuntu18.04的发行版，但是不行，和真正的ubuntu18.04表现不一样。\n\n### 大小端问题\n\n注意发送的数据中ip和端口都是要经过htonl或htons转换的。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fli1553770945%2Fsynscan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fli1553770945%2Fsynscan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fli1553770945%2Fsynscan/lists"}