├── src ├── main │ ├── resources │ │ └── application.properties │ └── java │ │ └── com │ │ └── noisy │ │ └── phantom │ │ └── PhantomApplication.java └── test │ └── java │ └── com │ └── noisy │ └── phantom │ └── PhantomApplicationTests.java ├── proxy-grab ├── target │ ├── classes │ │ ├── META-INF │ │ │ └── proxy-grab.kotlin_module │ │ ├── com │ │ │ └── noisy │ │ │ │ ├── GrabCenter.class │ │ │ │ ├── entity │ │ │ │ └── AgentIp.class │ │ │ │ ├── utils │ │ │ │ ├── IPutils.class │ │ │ │ ├── SpringUtil.class │ │ │ │ ├── CodeGenerator.class │ │ │ │ ├── CodeGenerator$1.class │ │ │ │ ├── CodeGenerator$2.class │ │ │ │ └── SpringContextUtil.class │ │ │ │ ├── task │ │ │ │ ├── Upload5UTask.class │ │ │ │ ├── UploadXiciTask.class │ │ │ │ ├── UploadGoubanjiaTask.class │ │ │ │ └── UploadKuaidailiTask.class │ │ │ │ ├── mapper │ │ │ │ └── AgentIpMapper.class │ │ │ │ ├── service │ │ │ │ ├── IAgentIpService.class │ │ │ │ └── impl │ │ │ │ │ └── AgentIpServiceImpl.class │ │ │ │ └── controller │ │ │ │ └── AgentIpController.class │ │ ├── mapper │ │ │ └── AgentIpMapper.xml │ │ ├── application.yml │ │ └── spring.xml │ └── test-classes │ │ ├── META-INF │ │ └── proxy-grab.kotlin_module │ │ └── com │ │ └── noisy │ │ └── phantom │ │ ├── PhantomApplicationTests.class │ │ └── phantom │ │ └── PhantomApplicationTests.class ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── noisy │ │ │ │ ├── service │ │ │ │ ├── IAgentIpService.java │ │ │ │ └── impl │ │ │ │ │ └── AgentIpServiceImpl.java │ │ │ │ ├── controller │ │ │ │ └── AgentIpController.java │ │ │ │ ├── mapper │ │ │ │ └── AgentIpMapper.java │ │ │ │ ├── entity │ │ │ │ └── AgentIp.java │ │ │ │ ├── task │ │ │ │ ├── UploadGoubanjiaTask.java │ │ │ │ ├── Upload5UTask.java │ │ │ │ ├── UploadKuaidailiTask.java │ │ │ │ └── UploadXiciTask.java │ │ │ │ ├── GrabCenter.java │ │ │ │ └── utils │ │ │ │ ├── IPutils.java │ │ │ │ ├── SpringContextUtil.java │ │ │ │ ├── SpringUtil.java │ │ │ │ └── CodeGenerator.java │ │ └── resources │ │ │ ├── mapper │ │ │ └── AgentIpMapper.xml │ │ │ ├── agent_ip.sql │ │ │ └── spring.xml │ └── test │ │ └── java │ │ └── com │ │ └── noisy │ │ └── PhantomApplicationTest.java └── pom.xml ├── .gitattributes ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── public_shell.md ├── phantom-backend ├── target │ └── test-classes │ │ └── com │ │ └── noisy │ │ └── AppTest.class ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── noisy │ │ │ └── App.java │ └── test │ │ └── java │ │ └── com │ │ └── noisy │ │ └── AppTest.java └── pom.xml ├── proxy-kidd ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── noisy │ │ │ │ └── proxy │ │ │ │ ├── HttpProxyDetect.java │ │ │ │ ├── entity │ │ │ │ ├── ProtocolType.java │ │ │ │ ├── ProxyType.java │ │ │ │ ├── InputType.java │ │ │ │ ├── ProxyIp.java │ │ │ │ └── ProxyInfo.java │ │ │ │ ├── repository │ │ │ │ └── ProxyIpRepository.java │ │ │ │ ├── dao │ │ │ │ ├── ProxyInfoDao.java │ │ │ │ ├── AbstractProxyInfoDaoImpl.java │ │ │ │ └── ProxyInfoDaoFilempl.java │ │ │ │ ├── detector │ │ │ │ ├── ProxyDetector.java │ │ │ │ ├── ProxyDetectorFactory.java │ │ │ │ ├── AbstractProxyDetector.java │ │ │ │ ├── HTTPProxyDetector.java │ │ │ │ ├── Socks4ProxyDetector.java │ │ │ │ └── Socks5ProxyDetector.java │ │ │ │ ├── ProxyProbApplication.java │ │ │ │ ├── service │ │ │ │ └── ProxyIpService.java │ │ │ │ ├── util │ │ │ │ ├── IPLocationUtils.java │ │ │ │ ├── SpringContextUtils.java │ │ │ │ ├── IPFilterUtils.java │ │ │ │ ├── IPSegment.java │ │ │ │ └── IPPoolUtils.java │ │ │ │ ├── EmailReporter.java │ │ │ │ ├── TaskScheduler.java │ │ │ │ └── ProxyScanner.java │ │ └── resources-env │ │ │ ├── prod │ │ │ ├── application.yml │ │ │ └── logback.xml │ │ │ └── dev │ │ │ ├── application.yml │ │ │ └── logback.xml │ └── test │ │ └── java │ │ └── com │ │ └── noisy │ │ └── proxy │ │ └── AppTest.java ├── restart.sh └── pom.xml ├── phantom-master ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── noisy │ │ │ └── App.java │ └── test │ │ └── java │ │ └── com │ │ └── noisy │ │ └── AppTest.java └── pom.xml ├── README.md ├── .github └── FUNDING.yml ├── .gitignore ├── todo.md ├── pom.xml ├── mvnw.cmd └── mvnw /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/META-INF/proxy-grab.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /proxy-grab/target/test-classes/META-INF/proxy-grab.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /public_shell.md: -------------------------------------------------------------------------------- 1 | - 子模块生成命令 2 | `mvn archetype:generate -DgroupId=com.noisy -DartifactId=proxy-kidd -DinteractiveMode=false` 3 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip 2 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/GrabCenter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/GrabCenter.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/entity/AgentIp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/entity/AgentIp.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/IPutils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/IPutils.class -------------------------------------------------------------------------------- /phantom-backend/target/test-classes/com/noisy/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/phantom-backend/target/test-classes/com/noisy/AppTest.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/task/Upload5UTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/task/Upload5UTask.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/SpringUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/SpringUtil.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/mapper/AgentIpMapper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/mapper/AgentIpMapper.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/task/UploadXiciTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/task/UploadXiciTask.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/CodeGenerator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/CodeGenerator.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/CodeGenerator$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/CodeGenerator$1.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/CodeGenerator$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/CodeGenerator$2.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/service/IAgentIpService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/service/IAgentIpService.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/task/UploadGoubanjiaTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/task/UploadGoubanjiaTask.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/task/UploadKuaidailiTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/task/UploadKuaidailiTask.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/utils/SpringContextUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/utils/SpringContextUtil.class -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/controller/AgentIpController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/controller/AgentIpController.class -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/HttpProxyDetect.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | /** 4 | * @author lei.X 5 | * @date 2019/4/29 6 | */ 7 | public class HttpProxyDetect { 8 | } 9 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/com/noisy/service/impl/AgentIpServiceImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/classes/com/noisy/service/impl/AgentIpServiceImpl.class -------------------------------------------------------------------------------- /proxy-grab/target/test-classes/com/noisy/phantom/PhantomApplicationTests.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/test-classes/com/noisy/phantom/PhantomApplicationTests.class -------------------------------------------------------------------------------- /proxy-grab/target/test-classes/com/noisy/phantom/phantom/PhantomApplicationTests.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metatronxl/phantom/HEAD/proxy-grab/target/test-classes/com/noisy/phantom/phantom/PhantomApplicationTests.class -------------------------------------------------------------------------------- /phantom-master/src/main/java/com/noisy/App.java: -------------------------------------------------------------------------------- 1 | package com.noisy; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /phantom-backend/src/main/java/com/noisy/App.java: -------------------------------------------------------------------------------- 1 | package com.noisy; 2 | 3 | 4 | /** 5 | * Hello world! 6 | * 7 | */ 8 | public class App 9 | { 10 | public static void main( String[] args ) 11 | { 12 | System.out.println( "Hello World!" ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # phantom 2 | 3 | 全网环境下的代理扫描工具 4 | 5 | ## 功能 6 | - 支持对IPv4的全部扫描、v6地址的指定网段扫描 7 | - 支持指定http、https、sock4、sock5协议的扫描 8 | - 支持自定义ip列表和port的定向扫描 9 | - 提供常见ip代理服务网站的爬取功能,并录入高频ip库 10 | - 对录入数据库的代理ip进行定期验证 11 | 12 | ## TODO 13 | 14 | - 对录入数据库的ip设置打分机制 15 | - 针对代理需求给出代理接口 16 | 17 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/service/IAgentIpService.java: -------------------------------------------------------------------------------- 1 | package com.noisy.service; 2 | 3 | import com.noisy.entity.AgentIp; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | *

8 | * 服务类 9 | *

10 | * 11 | * @author liuzhaoce 12 | * @since 2019-05-05 13 | */ 14 | public interface IAgentIpService extends IService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/entity/ProtocolType.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.entity; 2 | 3 | /** 4 | * Created by kevin on 5/24/16. 5 | */ 6 | public enum ProtocolType { 7 | HTTP(0), 8 | SOCKS_V4(1), 9 | SOCKS_V5(2); 10 | 11 | private int type; 12 | 13 | ProtocolType(int type) { 14 | this.type = type; 15 | } 16 | 17 | public int getType() { 18 | return type; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/repository/ProxyIpRepository.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.repository; 2 | 3 | import com.noisy.proxy.entity.ProxyIp; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author lei.X 8 | * @date 2019/5/27 9 | */ 10 | public interface ProxyIpRepository extends JpaRepository{ 11 | 12 | 13 | ProxyIp findByIpAndPort(String ip,int port); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/dao/ProxyInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.dao; 2 | 3 | import com.noisy.proxy.entity.ProxyInfo; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * Created by kevin on 5/31/16. 9 | */ 10 | public interface ProxyInfoDao { 11 | 12 | public void insert(ProxyInfo proxyInfo); 13 | 14 | public void deleteByIPAndPort(String ip, int port); 15 | 16 | public void append(ProxyInfo proxyInfo, File distFile); 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/noisy/phantom/PhantomApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.noisy.phantom; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class PhantomApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/controller/AgentIpController.java: -------------------------------------------------------------------------------- 1 | package com.noisy.controller; 2 | 3 | 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | *

10 | * 前端控制器 11 | *

12 | * 13 | * @author liuzhaoce 14 | * @since 2019-05-05 15 | */ 16 | @RestController 17 | @RequestMapping("/agent-ip") 18 | public class AgentIpController { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/entity/ProxyType.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.entity; 2 | 3 | /** 4 | * @author lei.X 5 | * @date 2019/4/29 6 | */ 7 | public enum ProxyType { 8 | TRANSPARENT(0), 9 | ANONYMOUS(1), 10 | DISTORTING(2), 11 | HIGH_ANONYMOUS(3); 12 | 13 | private int type; 14 | 15 | ProxyType(int type) { 16 | this.type = type; 17 | } 18 | 19 | public int getType() { 20 | return type; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/ProxyDetector.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | /** 4 | * Created by lei.x on 5/24/19.. 5 | */ 6 | public interface ProxyDetector { 7 | /** 8 | * Detect the given IP and port, will return the proxy info if its a proxy. 9 | * 10 | * @param ip 11 | * @param port 12 | */ 13 | void detect(String ip, int port); 14 | 15 | /** 16 | * Reset the proxy detector. 17 | */ 18 | void reset(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/noisy/phantom/PhantomApplication.java: -------------------------------------------------------------------------------- 1 | package com.noisy.phantom; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | 8 | @SpringBootApplication 9 | @MapperScan("com.noisy") 10 | public class PhantomApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(PhantomApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/mapper/AgentIpMapper.java: -------------------------------------------------------------------------------- 1 | package com.noisy.mapper; 2 | 3 | import com.noisy.entity.AgentIp; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | *

9 | * Mapper 接口 10 | *

11 | * 12 | * @author liuzhaoce 13 | * @since 2019-05-05 14 | */ 15 | 16 | @Mapper 17 | public interface AgentIpMapper extends BaseMapper { 18 | 19 | int insertAgentIp(AgentIp agentIp); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/entity/InputType.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.entity; 2 | 3 | /** 4 | * Created by kevin on 8/22/16. 5 | */ 6 | public enum InputType { 7 | IP_LIST("ip_list"), 8 | IP_SEGMENTS("ip_segments"); 9 | 10 | InputType(String type){ 11 | this.type = type; 12 | } 13 | 14 | private String type; 15 | 16 | public String getType() { 17 | return type; 18 | } 19 | 20 | public boolean isThisType(String type){ 21 | return this.type.equals(type); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/dao/AbstractProxyInfoDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.dao; 2 | 3 | import com.noisy.proxy.entity.ProxyInfo; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * Created by kevin on 5/31/16. 9 | */ 10 | public abstract class AbstractProxyInfoDaoImpl implements ProxyInfoDao { 11 | 12 | @Override 13 | public void insert(ProxyInfo proxyInfo) { 14 | } 15 | 16 | @Override 17 | public void deleteByIPAndPort(String ip, int port) { 18 | } 19 | 20 | @Override 21 | public void append(ProxyInfo proxyInfo, File distFile) { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | /target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | ### NetBeans ### 21 | /nbproject/private/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | /build/ 27 | 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | 32 | ### Others ### 33 | commandIgnore.md 34 | /services 35 | /output 36 | proxy-kidd/target/* 37 | proxy-grab/target/* 38 | phantom-backend/target/classes/ 39 | phantom-backend/target/generated-sources/ 40 | phantom-backend/target/generated-test-sources/ 41 | proxy-grab/src/main/resources/application.yml -------------------------------------------------------------------------------- /todo.md: -------------------------------------------------------------------------------- 1 | ### TODO 2 | 3 | - 分发扫描任务:主节点负责管理和分发ip扫描任务,salve节点负责连接主节点和领取任务 4 | ```txt 5 | 初步构想是salve通过netty连接到master, 6 | master检测到有slave连接后会自动分发任务, 7 | slave完成后返回响应 8 | 9 | 一个IP segment 作为一个task由master进行分发 10 | 11 | master 使用定时任务扫描是否有连接上的slave机器 12 | 13 | salve 扫描完成后返回给master 结果, 数据则直接存贮进数据库 14 | 15 | 16 | 任务分发的数据库采用redis,所有IP_segment 放入list消息队列 17 | 18 | 19 | 20 | 21 | 现在的思路是phantom 分为phantom-master和phantom-salve, phantom-master专门做任务的分发和 22 | IP打分这类的工作,phantom-master将IP-segment存储进redis的消息队列(一个段/24作为一条数据),有salve连接上了就会分发 23 | 一个segment给它。 24 | 25 | salve和master通过netty进行通讯,这样可以动态的增减salve的个数 26 | 27 | 28 | 29 | ``` 30 | 31 | - IP打分机制 32 | - 开放使用端口 33 | 34 | - 数据库添加扫描的代理类型 35 | 36 | - 压测机器最多可以开多少个Channel -------------------------------------------------------------------------------- /phantom-backend/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.noisy 7 | phantom 8 | 0.0.1-SNAPSHOT 9 | 10 | com.noisy 11 | phantom-backend 12 | phantom-backend 13 | http://maven.apache.org 14 | 15 | 16 | 17 | com.noisy 18 | proxy-kidd 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/ProxyProbApplication.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 7 | 8 | /** 9 | * @author lei.X 10 | * @date 2019/4/29 11 | */ 12 | @SpringBootApplication 13 | @EnableJpaAuditing 14 | public class ProxyProbApplication { 15 | 16 | public static void main(String[] args) { 17 | ConfigurableApplicationContext context = SpringApplication.run(ProxyProbApplication.class, args); 18 | ProxyScanner bean = context.getBean(ProxyScanner.class); 19 | 20 | bean.start(); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/entity/AgentIp.java: -------------------------------------------------------------------------------- 1 | package com.noisy.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | *

12 | * 13 | *

14 | * 15 | * @author liuzhaoce 16 | * @since 2019-05-05 17 | */ 18 | @Data 19 | @EqualsAndHashCode(callSuper = false) 20 | @Accessors(chain = true) 21 | @AllArgsConstructor 22 | public class AgentIp implements Serializable { 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | private String ip; 27 | 28 | private String port; 29 | 30 | private String anonymity; 31 | 32 | private String type; 33 | 34 | private String location; 35 | 36 | private String operator; 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /phantom-backend/src/test/java/com/noisy/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.noisy; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /phantom-master/src/test/java/com/noisy/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.noisy; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/mapper/AgentIpMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | insert into agent_ip( 7 | ip, 8 | port, 9 | anonymity, 10 | type, 11 | location, 12 | operator 13 | ) values( 14 | #{ip}, 15 | #{port}, 16 | #{anonymity}, 17 | #{type}, 18 | #{location}, 19 | #{operator} 20 | ) on duplicate key update 21 | anonymity = #{anonymity}, 22 | type = #{type}, 23 | location = #{location}, 24 | operator = #{operator} 25 | 26 | 27 | -------------------------------------------------------------------------------- /proxy-kidd/src/test/java/com/noisy/proxy/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /proxy-grab/src/main/resources/mapper/AgentIpMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | insert into agent_ip( 7 | ip, 8 | port, 9 | anonymity, 10 | type, 11 | location, 12 | operator 13 | ) values( 14 | #{ip}, 15 | #{port}, 16 | #{anonymity}, 17 | #{type}, 18 | #{location}, 19 | #{operator} 20 | ) on duplicate key update 21 | anonymity = #{anonymity}, 22 | type = #{type}, 23 | location = #{location}, 24 | operator = #{operator} 25 | 26 | 27 | -------------------------------------------------------------------------------- /phantom-master/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.noisy 7 | phantom 8 | 0.0.1-SNAPSHOT 9 | 10 | com.noisy 11 | phantom-master 12 | 1.0-SNAPSHOT 13 | phantom-master 14 | http://maven.apache.org 15 | 16 | 17 | junit 18 | junit 19 | 3.8.1 20 | test 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 2525 3 | 4 | # 该配置的名称是固定的,不可以改变,否则将不能自动加载到数据源中 5 | spring: 6 | datasource: 7 | # 使用druid数据源 8 | type: com.alibaba.druid.pool.DruidDataSource 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | url: jdbc:mysql://139.224.187.178:3306/phantom?characterEncoding=utf-8&autoReconnect=true&useSSL=false 11 | username: root 12 | password: phantom 13 | filters: stat 14 | maxActive: 20 15 | initialSize: 1 16 | maxWait: 60000 17 | minIdle: 1 18 | timeBetweenEvictionRunsMillis: 60000 19 | minEvictableIdleTimeMillis: 300000 20 | validationQuery: select 1 FROM DUAL 21 | testWhileIdle: true 22 | testOnBorrow: false 23 | testOnReturn: false 24 | poolPreparedStatements: true 25 | maxOpenPreparedStatements: 20 26 | 27 | mybatis-plus: 28 | mapper-locations: classpath:/mapper/*Mapper.xml -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/task/UploadGoubanjiaTask.java: -------------------------------------------------------------------------------- 1 | package com.noisy.task; 2 | 3 | import com.noisy.service.impl.AgentIpServiceImpl; 4 | import com.virjar.dungproxy.client.httpclient.HttpInvoker; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * @Auther: liuzhaoce 13 | * @Date: 2019-05-05 17:13 14 | * @Description: 15 | */ 16 | 17 | @Component 18 | @Configuration 19 | @EnableScheduling 20 | public class UploadGoubanjiaTask { 21 | 22 | @Resource 23 | AgentIpServiceImpl agentIpService; 24 | 25 | // @Scheduled(fixedRate = 5000) 26 | private void configureTasks() { 27 | 28 | String s = HttpInvoker.get("http://www.goubanjia.com/"); 29 | 30 | // TODO : 爬取goubanjia的代理ip,页面分析较为繁琐,每个数字放在不同的标签里 31 | 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/service/impl/AgentIpServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.noisy.service.impl; 2 | 3 | import com.noisy.entity.AgentIp; 4 | import com.noisy.mapper.AgentIpMapper; 5 | import com.noisy.service.IAgentIpService; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.List; 11 | 12 | /** 13 | *

14 | * 服务实现类 15 | *

16 | * 17 | * @author liuzhaoce 18 | * @since 2019-05-05 19 | */ 20 | @Service 21 | public class AgentIpServiceImpl extends ServiceImpl implements IAgentIpService { 22 | 23 | @Resource 24 | private AgentIpMapper agentIpMapper; 25 | 26 | 27 | public void upload(List agentIpList) { 28 | for (AgentIp agentIp : agentIpList) { 29 | int code = agentIpMapper.insertAgentIp(agentIp); 30 | // log.info("return code: " + code); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /proxy-grab/src/test/java/com/noisy/PhantomApplicationTest.java: -------------------------------------------------------------------------------- 1 | //package com.noisy; 2 | // 3 | //import com.noisy.entity.AgentIp; 4 | //import com.noisy.mapper.AgentIpMapper; 5 | //import org.junit.Test; 6 | //import org.junit.runner.RunWith; 7 | //import org.springframework.beans.factory.annotation.Autowired; 8 | //import org.springframework.boot.test.context.SpringBootTest; 9 | //import org.springframework.test.context.junit4.SpringRunner; 10 | // 11 | //import java.util.List; 12 | // 13 | // 14 | //@RunWith(SpringRunner.class) 15 | //@SpringBootTest(classes = GrabCenter.class) 16 | //public class PhantomApplicationTest { 17 | // 18 | // @Autowired 19 | // private AgentIpMapper agentIpMapper; 20 | // 21 | // @Test 22 | // public void testSelect() { 23 | // System.out.println(("----- selectAll method test ------")); 24 | // List agentIpList = agentIpMapper.selectList(null); 25 | //// Assert.assertEquals(5, agentIpList.size()); 26 | // agentIpList.forEach(System.out::println); 27 | // } 28 | //} -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/ProxyDetectorFactory.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | import com.noisy.proxy.TaskScheduler; 4 | import com.noisy.proxy.entity.ProtocolType; 5 | 6 | /** 7 | * Created by lei.x on 5/24/19. 8 | */ 9 | public class ProxyDetectorFactory { 10 | /** 11 | * Create a new proxy detector with the given protocol type and task scheduler. 12 | * 13 | * @param protocolType ProtocolType 14 | * @param scheduler TaskSchedule Object 15 | * @return a ProxyDetector Object 16 | */ 17 | public static ProxyDetector createProxyDetector(ProtocolType protocolType, TaskScheduler scheduler) { 18 | switch (protocolType) { 19 | case HTTP: 20 | return new HTTPProxyDetector(scheduler); 21 | case SOCKS_V4: 22 | return new Socks4ProxyDetector(scheduler); 23 | case SOCKS_V5: 24 | return new Socks5ProxyDetector(scheduler); 25 | } 26 | 27 | return new HTTPProxyDetector(scheduler); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/GrabCenter.java: -------------------------------------------------------------------------------- 1 | package com.noisy; 2 | 3 | 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.builder.SpringApplicationBuilder; 9 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 10 | import org.springframework.context.ConfigurableApplicationContext; 11 | 12 | /** 13 | * @Auther: liuzhaoce 14 | * @Date: 2019-04-26 15:46 15 | * @Description: 16 | */ 17 | 18 | @SpringBootApplication 19 | @MapperScan("com.noisy") 20 | @Slf4j 21 | public class GrabCenter extends SpringBootServletInitializer { 22 | 23 | public static void main(String[] args) { 24 | 25 | //未使用,留下自建类使用Spring模块的方式 26 | ConfigurableApplicationContext context = SpringApplication.run(GrabCenter.class, args); 27 | } 28 | 29 | @Override 30 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 31 | return builder.sources(GrabCenter.class); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/utils/IPutils.java: -------------------------------------------------------------------------------- 1 | package com.noisy.utils; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @Auther: liuzhaoce 9 | * @Date: 2019-04-28 17:22 10 | * @Description: 11 | */ 12 | public class IPutils { 13 | 14 | 15 | /** 16 | * @Description: 拆分List 17 | * @param size 拆分成的每个List的大小 18 | * @param target 待拆分List 19 | */ 20 | public static List> createList(List target, int size) { 21 | 22 | List> listArr = Lists.newArrayList(); 23 | //获取被拆分的数组个数 24 | int arrSize = target.size() % size == 0 ? target.size() / size : target.size() / size + 1; 25 | for (int i = 0; i < arrSize; i++) { 26 | List sub = Lists.newArrayList(); 27 | //把指定索引数据放入到list中 28 | for (int j = i * size; j <= size * (i + 1) - 1; j++) { 29 | if (j <= target.size() - 1) { 30 | sub.add(target.get(j)); 31 | } 32 | } 33 | listArr.add(sub); 34 | } 35 | return listArr; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /proxy-grab/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.noisy 7 | phantom 8 | 0.0.1-SNAPSHOT 9 | 10 | com.noisy 11 | proxy-grab 12 | proxy-grab 13 | http://maven.apache.org 14 | 15 | 16 | junit 17 | junit 18 | 3.8.1 19 | test 20 | 21 | 22 | com.virjar 23 | dungproxy-client 24 | 0.0.8 25 | 26 | 27 | junit 28 | junit 29 | test 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/entity/ProxyIp.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.entity; 2 | 3 | import lombok.Data; 4 | import org.springframework.data.annotation.CreatedDate; 5 | import org.springframework.data.annotation.LastModifiedDate; 6 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | /** 12 | * @author lei.X 13 | * @date 2019/5/27 14 | */ 15 | @Entity 16 | @Data 17 | @Table(name = "proxy_ip") 18 | @EntityListeners(AuditingEntityListener.class) 19 | public class ProxyIp { 20 | 21 | @Id 22 | @GeneratedValue 23 | private Long id; 24 | @Column(nullable = false) 25 | private String ip; 26 | @Column 27 | private int protocol; 28 | @Column(nullable = false) 29 | private int port; 30 | @Column(nullable = false) 31 | private int type; 32 | @Column 33 | private String location; 34 | 35 | /** 36 | * 创建时间 37 | */ 38 | @CreatedDate 39 | @Column(name = "create_time") 40 | private Date createTime; 41 | 42 | /** 43 | * 修改时间 44 | */ 45 | @LastModifiedDate 46 | @Column(name = "modify_time") 47 | private Date modifyTime; 48 | } 49 | -------------------------------------------------------------------------------- /proxy-grab/src/main/resources/agent_ip.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : proxy_grab 5 | Source Server Type : MySQL 6 | Source Server Version : 80016 7 | Source Host : localhost:3306 8 | Source Schema : proxy_grab 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 80016 12 | File Encoding : 65001 13 | 14 | Date: 06/05/2019 15:37:53 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for agent_ip 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `agent_ip`; 24 | CREATE TABLE `agent_ip` ( 25 | `ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 26 | `port` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 27 | `anonymity` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 28 | `type` varchar(255) DEFAULT NULL, 29 | `location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 30 | `operator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 31 | PRIMARY KEY (`port`,`ip`) USING BTREE 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 33 | 34 | SET FOREIGN_KEY_CHECKS = 1; 35 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/dao/ProxyInfoDaoFilempl.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.dao; 2 | 3 | import com.noisy.proxy.entity.ProxyInfo; 4 | import com.noisy.proxy.entity.ProxyIp; 5 | import com.noisy.proxy.repository.ProxyIpRepository; 6 | import com.noisy.proxy.service.ProxyIpService; 7 | import com.noisy.proxy.util.SpringContextUtils; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.io.FileUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | 17 | /** 18 | * Created by kevin on 5/31/16. 19 | */ 20 | 21 | @Slf4j 22 | public class ProxyInfoDaoFilempl extends AbstractProxyInfoDaoImpl { 23 | 24 | 25 | ProxyIpService proxyIpService = (ProxyIpService) SpringContextUtils.getApplicationContext().getBean("proxyIpService"); 26 | 27 | @Override 28 | public void append(ProxyInfo proxyInfo, File distFile) { 29 | try { 30 | FileUtils.write(distFile, proxyInfo.toString(), "UTF-8", true); 31 | proxyIpService.saveNewProxyIp(proxyInfo); 32 | } catch (IOException e) { 33 | log.error("An exception occurred when appending a new proxy info to the file: {}", 34 | distFile.getAbsolutePath()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/service/ProxyIpService.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.service; 2 | 3 | import com.noisy.proxy.entity.ProxyInfo; 4 | import com.noisy.proxy.entity.ProxyIp; 5 | import com.noisy.proxy.repository.ProxyIpRepository; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import javax.transaction.Transactional; 11 | 12 | /** 13 | * @author lei.X 14 | * @date 2019/5/27 15 | */ 16 | @Service("proxyIpService") 17 | @Slf4j 18 | @Transactional 19 | public class ProxyIpService { 20 | 21 | @Resource 22 | private ProxyIpRepository proxyIpRepository; 23 | 24 | 25 | /** 26 | * 如果已经存在IP与port相同的数据,则不重复插入 27 | * @param proxyInfo 28 | */ 29 | public void saveNewProxyIp(ProxyInfo proxyInfo){ 30 | 31 | 32 | String ip = proxyInfo.getIp(); 33 | int port = proxyInfo.getPort(); 34 | 35 | 36 | ProxyIp dbProxy = proxyIpRepository.findByIpAndPort(ip,port); 37 | if (dbProxy == null){ 38 | ProxyIp proxyIp = new ProxyIp(); 39 | proxyIp.setIp(proxyInfo.getIp()); 40 | proxyIp.setPort(proxyInfo.getPort()); 41 | proxyIp.setType(proxyInfo.getType()); 42 | proxyIp.setLocation(proxyInfo.getLocation()); 43 | proxyIp.setProtocol(proxyInfo.getProtocol()); 44 | proxyIpRepository.save(proxyIp); 45 | log.info("new proxyInfo insert into database success"); 46 | }else{ 47 | log.warn("ip-port has been insert into database, so refuse insert"); 48 | } 49 | } 50 | 51 | 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/util/IPLocationUtils.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import us.monoid.web.JSONResource; 6 | import us.monoid.web.Resty; 7 | 8 | /** 9 | * Created by kevin on 5/27/16. 10 | */ 11 | public class IPLocationUtils { 12 | private final static Logger log = LoggerFactory.getLogger(IPLocationUtils.class); 13 | private final static Resty restClient = new Resty(); 14 | private final static String geoURL ="http://maxcd03-dev05/geoip/ip2coor/"; 15 | 16 | public static String getLocation(final String ip) { 17 | String location = null; 18 | String url = geoURL + ip; 19 | try { 20 | JSONResource response = restClient.json(url); 21 | location = constructLocation(response); 22 | } catch (Exception e) { 23 | log.warn("Failed to retrieve the IP location from GEO service: {}", url); 24 | } 25 | 26 | return location; 27 | } 28 | 29 | private static String constructLocation(JSONResource resource) throws Exception { 30 | if (resource == null) { 31 | return null; 32 | } 33 | String country = resource.get("country").toString(); 34 | if (country == null) { 35 | country = ""; 36 | } 37 | String province = resource.get("province").toString(); 38 | if (province == null) { 39 | province = ""; 40 | } 41 | String city = resource.get("city").toString(); 42 | 43 | StringBuilder location = new StringBuilder(country); 44 | if (!country.equals(province)) { 45 | location.append(province); 46 | } 47 | if (!province.equals(city)) { 48 | location.append(city); 49 | } 50 | 51 | return location.toString(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/util/SpringContextUtils.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author lei.X 10 | * @date 2019/5/24 11 | */ 12 | @Component 13 | public class SpringContextUtils implements ApplicationContextAware { 14 | 15 | /** 16 | * 上下文对象实例 17 | */ 18 | private static ApplicationContext applicationContext; 19 | 20 | @Override 21 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 22 | if (SpringContextUtils.applicationContext == null) { 23 | SpringContextUtils.applicationContext = applicationContext; 24 | } 25 | } 26 | 27 | /** 28 | * 获取applicationContext 29 | * 30 | * @return 31 | */ 32 | public static ApplicationContext getApplicationContext() { 33 | return applicationContext; 34 | } 35 | 36 | /** 37 | * 通过name获取 Bean. 38 | * 39 | * @param name 40 | * @return 41 | */ 42 | public static Object getBean(String name) { 43 | return getApplicationContext().getBean(name); 44 | } 45 | 46 | /** 47 | * 通过class获取Bean. 48 | * 49 | * @param clazz 50 | * @param 51 | * @return 52 | */ 53 | public static T getBean(Class clazz) { 54 | return getApplicationContext().getBean(clazz); 55 | } 56 | 57 | /** 58 | * 通过name,以及Clazz返回指定的Bean 59 | * 60 | * @param name 61 | * @param clazz 62 | * @param 63 | * @return 64 | */ 65 | public static T getBean(String name, Class clazz) { 66 | return getApplicationContext().getBean(name, clazz); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/utils/SpringContextUtil.java: -------------------------------------------------------------------------------- 1 | package com.noisy.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | 8 | /** 9 | * @Auther: liuzhaoce 10 | * @Date: 2019-04-29 17:03 11 | * @Description: 12 | */ 13 | 14 | public class SpringContextUtil implements ApplicationContextAware { 15 | 16 | private static ApplicationContext applicationContext; // Spring应用上下文环境 17 | 18 | // 下面的这个方法上加了@Override注解,原因是继承ApplicationContextAware接口是必须实现的方法 19 | @Override 20 | public void setApplicationContext(ApplicationContext applicationContext) 21 | throws BeansException { 22 | SpringContextUtil.applicationContext = applicationContext; 23 | } 24 | 25 | public static ApplicationContext getApplicationContext() { 26 | return applicationContext; 27 | } 28 | 29 | public static Object getBean(String name) throws BeansException { 30 | return applicationContext.getBean(name); 31 | } 32 | 33 | public static Object getBean(String name, Class requiredType) 34 | throws BeansException { 35 | return applicationContext.getBean(name, requiredType); 36 | } 37 | 38 | public static boolean containsBean(String name) { 39 | return applicationContext.containsBean(name); 40 | } 41 | 42 | public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { 43 | return applicationContext.isSingleton(name); 44 | } 45 | 46 | public static Class getType(String name) throws NoSuchBeanDefinitionException { 47 | return applicationContext.getType(name); 48 | } 49 | 50 | public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { 51 | return applicationContext.getAliases(name); 52 | } 53 | } -------------------------------------------------------------------------------- /proxy-kidd/restart.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | PROJECT_NAME="proxy-kidd" 5 | JAR_NAME="proxy-kidd-1.0-SNAPSHOT.jar" 6 | 7 | 8 | function compile() 9 | { 10 | echo "rebuild project" 11 | mvn clean package -Pprod -Dmaven.test.skip=true 12 | } 13 | 14 | function hasCodeUpdate() 15 | { 16 | git fetch origin master 17 | diff=`git diff FETCH_HEAD` 18 | if [ ! -n "$diff" ] ;then 19 | return 0 20 | fi 21 | echo "服务器代码更新" 22 | return 1 23 | } 24 | 25 | function pullNewCode() 26 | { 27 | git fetch origin master 28 | git merge 29 | echo "拉取新代码完成" 30 | 31 | } 32 | 33 | function checkServer() 34 | { 35 | target=`ps -ef | grep "${PROJECT_NAME}" | grep "java" | grep -v "grep"` 36 | if [ -n "${target}" ] ;then 37 | echo "服务正常启动" 38 | echo "${target}" 39 | return 0; 40 | fi 41 | 42 | #这句代码有问题,判断不生效 43 | if [ ! -f "target/${JAR_NAME}" ] ;then 44 | echo "项目执行文件不存在,重新编译" 45 | compile 46 | fi 47 | 48 | echo "start server" 49 | 50 | nohup java -jar ./target/${JAR_NAME} >/dev/null 2>&1 & 51 | 52 | 53 | target=`ps -ef | grep "${PROJECT_NAME}" | grep "java" | grep -v "grep"` 54 | if [ -n "$target" ] ;then 55 | echo "server start success" 56 | echo "$target" 57 | return 0 58 | else 59 | echo "new server start failed please check IT!!!" 60 | return 1 61 | fi 62 | } 63 | 64 | function killServer(){ 65 | target=`ps -ef | grep "${PROJECT_NAME}" | grep "java" | grep -v "grep"` 66 | if [ -n "$target" ] ;then 67 | echo "kill old server process" 68 | ps -ef | grep "${PROJECT_NAME}" | grep -v "grep" | awk '{print $2}' | xargs kill -9 69 | echo `ps -ef | grep "${PROJECT_NAME}" | grep -v "grep"` 70 | 71 | fi 72 | } 73 | 74 | hasCodeUpdate 75 | updateStatus=$? 76 | 77 | if [ ! ${updateStatus} -eq 0 ] ;then 78 | killServer 79 | echo "clean code" 80 | git clean -dfx 81 | echo "pull new code" 82 | git pull 83 | # pullNewCode 84 | compile 85 | fi 86 | checkServer -------------------------------------------------------------------------------- /proxy-kidd/src/main/resources-env/prod/application.yml: -------------------------------------------------------------------------------- 1 | # mysql database 2 | server: 3 | port: 5597 4 | 5 | spring: 6 | datasource: 7 | type: com.alibaba.druid.pool.DruidDataSource 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://115.28.58.82:3306/phantom?characterEncoding=utf-8&autoReconnect=true&useSSL=false 10 | username: root 11 | password: phantom 12 | filters: stat 13 | maxActive: 20 14 | initialSize: 1 15 | maxWait: 60000 16 | minIdle: 1 17 | timeBetweenEvictionRunsMillis: 60000 18 | minEvictableIdleTimeMillis: 300000 19 | validationQuery: select 1 FROM DUAL 20 | testWhileIdle: true 21 | testOnBorrow: false 22 | testOnReturn: false 23 | poolPreparedStatements: true 24 | maxOpenPreparedStatements: 20 25 | 26 | jpa: 27 | hibernate: 28 | ddl-auto: update 29 | database-platform: org.hibernate.dialect.MySQL5InnoDBDialect 30 | show-sql: true 31 | servlet: 32 | multipart: 33 | max-request-size: 300MB 34 | max-file-size: 1000MB 35 | 36 | #ip_segments ip_list 37 | input_type: ip_segments 38 | 39 | # Ports need to detect 40 | data.address: /root/proxyScanner/ip_data/ 41 | detection.ports.file: /root/proxyScanner/ip_data/DetectPorts.txt 42 | fileter_ip: /root/proxyScanner/ip_data/FilterIPList.txt 43 | 44 | # Scanning frequency configuration 45 | # Start time in 24 hours(0 ~ 23), set -1 to start the scanning immediately 46 | inland.http.scanner.start: -1 47 | inland.socks4.scanner.start: -1 48 | inland.socks5.scanner.start: -1 49 | # Interval in hours, set -1 to close the scanner 50 | inland.http.scanner.interval: 24 51 | inland.socks4.scanner.interval: -1 52 | inland.socks5.scanner.interval: -1 53 | 54 | # Start time in 24 hours(0 ~ 23), set -1 to start the scanning immediately 55 | abroad.http.scanner.start: 15 56 | abroad.socks4.scanner.start: 15 57 | abroad.socks5.scanner.start: 15 58 | # Interval in hours, set -1 to close the scanner 59 | abroad.http.scanner.interval: -1 60 | abroad.socks4.scanner.interval: -1 61 | abroad.socks5.scanner.interval: -1 -------------------------------------------------------------------------------- /proxy-kidd/src/main/resources-env/dev/application.yml: -------------------------------------------------------------------------------- 1 | # mysql database 2 | server: 3 | port: 5597 4 | 5 | spring: 6 | datasource: 7 | type: com.alibaba.druid.pool.DruidDataSource 8 | driver-class-name: com.mysql.jdbc.Driver 9 | url: jdbc:mysql://115.28.58.82:3306/phantom?characterEncoding=utf-8&autoReconnect=true&useSSL=false 10 | username: root 11 | password: phantom 12 | filters: stat 13 | # 最大连接数 14 | maxActive: 20 15 | initialSize: 1 16 | maxWait: 60000 17 | minIdle: 1 18 | timeBetweenEvictionRunsMillis: 60000 19 | minEvictableIdleTimeMillis: 300000 20 | validationQuery: select 1 FROM DUAL 21 | testWhileIdle: true 22 | testOnBorrow: false 23 | testOnReturn: false 24 | poolPreparedStatements: true 25 | maxOpenPreparedStatements: 20 26 | 27 | jpa: 28 | hibernate: 29 | ddl-auto: update 30 | database-platform: org.hibernate.dialect.MySQL5InnoDBDialect 31 | show-sql: true 32 | servlet: 33 | multipart: 34 | max-request-size: 300MB 35 | max-file-size: 1000MB 36 | 37 | #ip_segments ip_list 38 | input_type: ip_segments 39 | 40 | # Ports need to detect 41 | data.address: /Users/xulei2/data/ip_data/ 42 | detection.ports.file: /Users/xulei2/data/ip_data/DetectPorts.txt 43 | fileter_ip: Users/xulei2/data/ip_data/FilterIPList.txt 44 | 45 | # Scanning frequency configuration 46 | # Start time in 24 hours(0 ~ 23), set -1 to start the scanning immediately 47 | inland.http.scanner.start: -1 48 | inland.socks4.scanner.start: -1 49 | inland.socks5.scanner.start: -1 50 | # Interval in hours, set -1 to close the scanner 51 | inland.http.scanner.interval: 24 52 | inland.socks4.scanner.interval: -1 53 | inland.socks5.scanner.interval: -1 54 | 55 | # Start time in 24 hours(0 ~ 23), set -1 to start the scanning immediately 56 | abroad.http.scanner.start: 15 57 | abroad.socks4.scanner.start: 15 58 | abroad.socks5.scanner.start: 15 59 | # Interval in hours, set -1 to close the scanner 60 | abroad.http.scanner.interval: -1 61 | abroad.socks4.scanner.interval: -1 62 | abroad.socks5.scanner.interval: -1 -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/utils/SpringUtil.java: -------------------------------------------------------------------------------- 1 | package com.noisy.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @Auther: liuzhaoce 10 | * @Date: 2019-04-29 17:19 11 | * @Description: 12 | */ 13 | 14 | @Component 15 | public class SpringUtil implements ApplicationContextAware { 16 | private static ApplicationContext applicationContext = null; 17 | 18 | @Override 19 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 20 | if(SpringUtil.applicationContext == null){ 21 | SpringUtil.applicationContext = applicationContext; 22 | } 23 | System.out.println("---------------------------------------------------------------------"); 24 | System.out.println("---------------------------------------------------------------------"); 25 | System.out.println("---------------com.kfit.base.util.SpringUtil------------------------------------------------------"); 26 | System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="+SpringUtil.applicationContext+"========"); 27 | System.out.println("---------------------------------------------------------------------"); 28 | } 29 | 30 | //获取applicationContext 31 | public static ApplicationContext getApplicationContext() { 32 | return applicationContext; 33 | } 34 | 35 | //通过name获取 Bean. 36 | public static Object getBean(String name){ 37 | return getApplicationContext().getBean(name); 38 | } 39 | 40 | //通过class获取Bean. 41 | public static T getBean(Class clazz){ 42 | return getApplicationContext().getBean(clazz); 43 | } 44 | 45 | //通过name,以及Clazz返回指定的Bean 46 | public static T getBean(String name,Class clazz){ 47 | return getApplicationContext().getBean(name, clazz); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/util/IPFilterUtils.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.util; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Created by Lei.x on 5/6/19. 8 | */ 9 | public class IPFilterUtils { 10 | private final static long longMulticastIP = IPSegment.ipToLong("224.0.0.0"); 11 | private final static long classAPrivateIPStart = IPSegment.ipToLong("10.0.0.0"); 12 | private final static long classAPrivateIPEnd = IPSegment.ipToLong("10.255.255.255"); 13 | private final static long classBPrivateIPStart = IPSegment.ipToLong("172.16.0.0"); 14 | private final static long classBPrivateIPEnd = IPSegment.ipToLong("172.31.255.255"); 15 | private final static long classCPrivateIPStart = IPSegment.ipToLong("192.168.0.0"); 16 | private final static long classCPrivateIPEnd = IPSegment.ipToLong("192.168.255.255"); 17 | 18 | private final static IPFilterUtils _Instance = new IPFilterUtils(); 19 | 20 | private Set _FilterIPList = new HashSet(){ 21 | { 22 | add("139.219.135.92"); 23 | add("185.12.64.0"); 24 | add("185.12.64.1"); 25 | add("185.12.64.2"); 26 | add("185.12.64.3"); 27 | add("104.20.65.24"); 28 | 29 | } 30 | }; 31 | 32 | 33 | 34 | private IPFilterUtils() { 35 | 36 | } 37 | 38 | public static IPFilterUtils getInstance() { 39 | return _Instance; 40 | } 41 | 42 | public boolean needFilter(final String ip) { 43 | if (_FilterIPList.contains(ip)) { 44 | return true; 45 | } 46 | 47 | return isPrivateIPOrMulticastIP(ip); 48 | } 49 | 50 | public boolean isPrivateIPOrMulticastIP(final String ip) { 51 | long longIp = IPSegment.ipToLong(ip); 52 | if (longIp >= longMulticastIP) { 53 | return true; 54 | } 55 | 56 | if ((longIp >= classAPrivateIPStart && longIp <= classAPrivateIPEnd) 57 | || (longIp >= classBPrivateIPStart && longIp <= classBPrivateIPEnd) 58 | || (longIp >= classCPrivateIPStart && longIp <= classCPrivateIPEnd)) { 59 | return true; 60 | } 61 | 62 | return false; 63 | } 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/task/Upload5UTask.java: -------------------------------------------------------------------------------- 1 | package com.noisy.task; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.noisy.entity.AgentIp; 5 | import com.noisy.service.impl.AgentIpServiceImpl; 6 | import com.noisy.utils.IPutils; 7 | import com.virjar.dungproxy.client.httpclient.HttpInvoker; 8 | import com.virjar.sipsoup.exception.XpathSyntaxErrorException; 9 | import com.virjar.sipsoup.parse.XpathParser; 10 | import org.jsoup.Jsoup; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.scheduling.annotation.EnableScheduling; 13 | import org.springframework.scheduling.annotation.Scheduled; 14 | import org.springframework.stereotype.Component; 15 | 16 | import javax.annotation.Resource; 17 | import java.time.LocalDateTime; 18 | import java.util.List; 19 | 20 | /** 21 | * @Auther: liuzhaoce 22 | * @Date: 2019-04-30 20:42 23 | * @Description: 24 | */ 25 | 26 | @Component 27 | @Configuration 28 | @EnableScheduling 29 | public class Upload5UTask { 30 | 31 | @Resource 32 | AgentIpServiceImpl agentIpService; 33 | 34 | @Scheduled(fixedRate = 5000) 35 | private void configureTasks() { 36 | 37 | try { 38 | String s = HttpInvoker.get("http://www.data5u.com/free/index.html"); 39 | List msg = XpathParser.compile("//css('.wlist')::ul[position() > 1]/span/li/text()").evaluateToString(Jsoup.parse(s)); 40 | List agentIPs = msgToIP(msg); 41 | System.out.println(agentIPs); 42 | agentIpService.upload(agentIPs); 43 | System.err.println("爬取无忧代理 定时任务时间: " + LocalDateTime.now()); 44 | } catch (XpathSyntaxErrorException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | } 49 | 50 | private static List msgToIP(List msg) { 51 | 52 | List> listArr = IPutils.createList(msg, 9); 53 | List agentIPList = Lists.newArrayList(); 54 | for (List item : listArr) { 55 | AgentIp agentIp = new AgentIp(item.get(0), item.get(1), item.get(2), item.get(3), item.get(4) + " " + item.get(5), item.get(6)); 56 | agentIPList.add(agentIp); 57 | } 58 | return agentIPList; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /proxy-grab/target/classes/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /proxy-kidd/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.noisy 8 | phantom 9 | 0.0.1-SNAPSHOT 10 | 11 | com.noisy 12 | proxy-kidd 13 | 1.0-SNAPSHOT 14 | proxy-kidd 15 | http://maven.apache.org 16 | 17 | 18 | 19 | 20 | 21 | junit 22 | junit 23 | 3.8.1 24 | test 25 | 26 | 27 | 28 | 29 | 30 | 31 | dev 32 | 33 | dev 34 | 35 | 36 | true 37 | 38 | 39 | 40 | 41 | src/main/resources-env/dev 42 | 43 | 44 | src/main/resources 45 | 46 | 47 | 48 | 49 | 50 | 51 | prod 52 | 53 | prod 54 | 55 | 56 | 57 | 58 | src/main/resources-env/prod 59 | 60 | 61 | src/main/resources 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /proxy-grab/src/main/resources/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/entity/ProxyInfo.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.entity; 2 | 3 | /** 4 | * Created by kevin on 5/24/16. 5 | */ 6 | public class ProxyInfo { 7 | private String ip; 8 | private int protocol; 9 | private int port; 10 | private int type; 11 | private String location; 12 | private long updateTime; 13 | 14 | public ProxyInfo() { 15 | } 16 | 17 | public ProxyInfo(String ip, int protocol, int port, int type, long updateTime) { 18 | this.ip = ip; 19 | this.protocol = protocol; 20 | this.port = port; 21 | this.type = type; 22 | this.updateTime = updateTime; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | StringBuilder stringBuilder = new StringBuilder(ip); 28 | stringBuilder.append(","); 29 | stringBuilder.append(protocol); 30 | stringBuilder.append(","); 31 | stringBuilder.append(port); 32 | stringBuilder.append(","); 33 | stringBuilder.append(type); 34 | stringBuilder.append(","); 35 | stringBuilder.append(location); 36 | stringBuilder.append(","); 37 | stringBuilder.append(updateTime); 38 | stringBuilder.append("\n"); 39 | 40 | return stringBuilder.toString(); 41 | } 42 | 43 | public String getIp() { 44 | return ip; 45 | } 46 | 47 | public void setIp(String ip) { 48 | this.ip = ip; 49 | } 50 | 51 | public int getProtocol() { 52 | return protocol; 53 | } 54 | 55 | public void setProtocol(int protocol) { 56 | this.protocol = protocol; 57 | } 58 | 59 | public int getPort() { 60 | return port; 61 | } 62 | 63 | public void setPort(int port) { 64 | this.port = port; 65 | } 66 | 67 | public int getType() { 68 | return type; 69 | } 70 | 71 | public void setType(int type) { 72 | this.type = type; 73 | } 74 | 75 | public String getLocation() { 76 | return location; 77 | } 78 | 79 | public void setLocation(String location) { 80 | this.location = location; 81 | } 82 | 83 | public long getUpdateTime() { 84 | return updateTime; 85 | } 86 | 87 | public void setUpdateTime(long updateTime) { 88 | this.updateTime = updateTime; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/task/UploadKuaidailiTask.java: -------------------------------------------------------------------------------- 1 | package com.noisy.task; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.noisy.entity.AgentIp; 5 | import com.noisy.service.impl.AgentIpServiceImpl; 6 | import com.noisy.utils.IPutils; 7 | import com.virjar.dungproxy.client.httpclient.HttpInvoker; 8 | import com.virjar.sipsoup.exception.XpathSyntaxErrorException; 9 | import com.virjar.sipsoup.parse.XpathParser; 10 | import org.jsoup.Jsoup; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.scheduling.annotation.EnableScheduling; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.Resource; 16 | import java.time.LocalDateTime; 17 | import java.util.List; 18 | 19 | /** 20 | * @Auther: liuzhaoce 21 | * @Date: 2019-05-05 10:48 22 | * @Description: 23 | */ 24 | 25 | @Component 26 | @Configuration 27 | @EnableScheduling 28 | public class UploadKuaidailiTask { 29 | 30 | @Resource 31 | AgentIpServiceImpl agentIpService; 32 | 33 | // @Scheduled(fixedRate = 5000) 34 | private void configureTasks() { 35 | 36 | try { 37 | String s = HttpInvoker.get("https://www.kuaidaili.com/free/"); 38 | List msg = XpathParser.compile("//css('.con-body')::div/div/table/tbody/tr/td/text()").evaluateToString(Jsoup.parse(s)); 39 | List agentIps = msgToIP(msg, 7); 40 | System.out.println(agentIps); 41 | agentIpService.upload(agentIps); 42 | System.err.println("爬取快代理 定时任务时间: " + LocalDateTime.now()); 43 | } catch (XpathSyntaxErrorException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | /** 49 | * 50 | * @Description: msg转换为 List 51 | */ 52 | public static List msgToIP(List msg, int size) { 53 | 54 | List> listArr = IPutils.createList(msg, size); 55 | List agentIPList = Lists.newArrayList(); 56 | for (List item : listArr) { 57 | String[] bits = item.get(4).split(" "); 58 | String operator = bits[bits.length - 1]; 59 | String location = item.get(4).substring(0, item.get(4).indexOf(operator)); 60 | AgentIp agentIp = new AgentIp(item.get(0), item.get(1), item.get(2), item.get(3), location, operator); 61 | agentIPList.add(agentIp); 62 | } 63 | return agentIPList; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/task/UploadXiciTask.java: -------------------------------------------------------------------------------- 1 | package com.noisy.task; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.noisy.entity.AgentIp; 5 | import com.noisy.service.impl.AgentIpServiceImpl; 6 | import com.noisy.utils.IPutils; 7 | import com.virjar.dungproxy.client.httpclient.HttpInvoker; 8 | import com.virjar.sipsoup.exception.XpathSyntaxErrorException; 9 | import com.virjar.sipsoup.parse.XpathParser; 10 | import org.jsoup.Jsoup; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.scheduling.annotation.EnableScheduling; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.Resource; 16 | import java.time.LocalDateTime; 17 | import java.util.List; 18 | 19 | /** 20 | * @Auther: liuzhaoce 21 | * @Date: 2019-05-05 15:38 22 | * @Description: 23 | */ 24 | 25 | @Component 26 | @Configuration 27 | @EnableScheduling 28 | public class UploadXiciTask { 29 | 30 | @Resource 31 | AgentIpServiceImpl agentIpService; 32 | 33 | // @Scheduled(fixedRate = 5000) 34 | private void configureTasks() { 35 | 36 | try { 37 | String s = HttpInvoker.get("https://www.xicidaili.com/nn/1"); 38 | List msg = XpathParser.compile("//css('#ip_list')::tbody/tr[position() > 1]/td/text()").evaluateToString(Jsoup.parse(s)); 39 | List location = XpathParser.compile("//css('#ip_list')::tbody/tr[position() > 1]/td/a/text()").evaluateToString(Jsoup.parse(s)); 40 | System.out.println(msg); 41 | System.out.println(location); 42 | List agentIPs = msgToIP(msg, location); 43 | System.out.println(agentIPs); 44 | agentIpService.upload(agentIPs); 45 | System.err.println("爬取西刺代理 定时任务时间: " + LocalDateTime.now()); 46 | } catch (XpathSyntaxErrorException e) { 47 | e.printStackTrace(); 48 | } 49 | 50 | } 51 | 52 | private static List msgToIP(List msg, List location) { 53 | 54 | List> listArr = IPutils.createList(msg, 10); 55 | List agentIPList = Lists.newArrayList(); 56 | int i = 0; 57 | for (List item : listArr) { 58 | String loc = ""; 59 | if (location.size() > i){ 60 | loc = location.get(i); 61 | } 62 | AgentIp agentIp = new AgentIp(item.get(1), item.get(2), item.get(4), item.get(5), loc, ""); 63 | agentIPList.add(agentIp); 64 | i++; 65 | } 66 | return agentIPList; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/resources-env/dev/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | ${logDir}/${projectName}/${projectName}.log 19 | 20 | ${logDir}/${projectName}/${projectName}-%d{yyyy-MM-dd}.zip 21 | ${maxHistory} 22 | 23 | 24 | ${CONSOLE_LOG_PATTERN} 25 | 26 | 27 | 28 | 29 | 30 | ERROR 31 | ACCEPT 32 | DENY 33 | 34 | ${logDir}/${projectName}/${projectName}-error.log 35 | 36 | ${logDir}/${projectName}/${projectName}-error-%d{yyyy-MM-dd}.zip 37 | ${errorMaxHistory} 38 | 39 | 40 | ${CONSOLE_LOG_PATTERN} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ${CONSOLE_LOG_PATTERN} 50 | 51 | 52 | 53 | DEBUG 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/resources-env/prod/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | ${logDir}/${projectName}/${projectName}.log 19 | 20 | ${logDir}/${projectName}/${projectName}-%d{yyyy-MM-dd}.zip 21 | ${maxHistory} 22 | 23 | 24 | ${CONSOLE_LOG_PATTERN} 25 | 26 | 27 | 28 | 29 | 30 | ERROR 31 | ACCEPT 32 | DENY 33 | 34 | ${logDir}/${projectName}/${projectName}-error.log 35 | 36 | ${logDir}/${projectName}/${projectName}-error-%d{yyyy-MM-dd}.zip 37 | ${errorMaxHistory} 38 | 39 | 40 | ${CONSOLE_LOG_PATTERN} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ${CONSOLE_LOG_PATTERN} 50 | 51 | 52 | 53 | DEBUG 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/AbstractProxyDetector.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | import com.noisy.proxy.entity.ProxyType; 4 | import com.noisy.proxy.util.IPPoolUtils; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.annotation.Resource; 12 | import java.net.InetAddress; 13 | import java.net.UnknownHostException; 14 | import java.text.SimpleDateFormat; 15 | import java.util.Date; 16 | import java.util.Set; 17 | 18 | /** 19 | * Created by lei.x on 5/24/19. 20 | */ 21 | 22 | public abstract class AbstractProxyDetector implements ProxyDetector { 23 | 24 | 25 | private static final Logger log = LoggerFactory.getLogger(AbstractProxyDetector.class); 26 | //TODO 代理检测URL配置优化 27 | private String proxyCheckerURL = "http://152.136.138.106:20000/test/parse"; 28 | private final int timeout = 10000; 29 | private String outputDir="output/"; 30 | 31 | 32 | public String getProxyCheckerURL() { 33 | return proxyCheckerURL; 34 | } 35 | 36 | public int getTimeout() { 37 | return timeout; 38 | } 39 | 40 | public String getLocalIP() throws UnknownHostException { 41 | 42 | String localIP = null; 43 | try { 44 | localIP = InetAddress.getLocalHost().getHostAddress(); 45 | } catch (UnknownHostException e) { 46 | localIP = null; 47 | log.error("An exception occurred when retrieving the local IP, exception: {}", e); 48 | throw new UnknownHostException("can't get local IP"); 49 | } 50 | 51 | return localIP; 52 | } 53 | 54 | public String getOutputTmpFilePath(String schedulerName) { 55 | if (StringUtils.isEmpty(schedulerName)) { 56 | throw new IllegalArgumentException("The scheduler name cannot be null!"); 57 | } 58 | 59 | StringBuilder filePath = new StringBuilder(outputDir); 60 | filePath.append(schedulerName); 61 | filePath.append("_"); 62 | filePath.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); 63 | filePath.append(".tmp"); 64 | return filePath.toString(); 65 | } 66 | 67 | public String retrieveOutputFilePath(String outputTmpFilePath) { 68 | String[] tmp = outputTmpFilePath.split("\\."); 69 | return tmp[0] + ".txt"; 70 | } 71 | 72 | public boolean validateIP(final String ip) { 73 | return IPPoolUtils.validateIP(ip); 74 | } 75 | 76 | public ProxyType checkProxyType(String proxyIp, String response) throws UnknownHostException { 77 | 78 | String currentLocalIP = getLocalIP(); 79 | Set responseIPs = IPPoolUtils.retrieveIPFromText(response); 80 | if (responseIPs == null || responseIPs.isEmpty()) { 81 | return null; 82 | } 83 | 84 | if (responseIPs.contains(currentLocalIP)) { 85 | return ProxyType.TRANSPARENT; 86 | } else if (responseIPs.contains(proxyIp)) { 87 | return ProxyType.ANONYMOUS; 88 | } else if (responseIPs.contains("0.0.0.0")) { 89 | return ProxyType.HIGH_ANONYMOUS; 90 | } else { 91 | return ProxyType.DISTORTING; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/util/IPSegment.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.util; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * Created by kevin on 5/25/16. 10 | */ 11 | public class IPSegment implements Comparable { 12 | private final static Logger log = LoggerFactory.getLogger(IPSegment.class); 13 | 14 | private Integer randomIndex; 15 | private String ipWithMaskBits; 16 | private String startIP; 17 | private String endIP; 18 | private String netMask; 19 | private long nextIp; 20 | private long startLongIP; 21 | private long endLongIP; 22 | 23 | public IPSegment(String startIP, String endIP, String netMask) { 24 | this.startIP = startIP; 25 | this.startLongIP = ipToLong(startIP); 26 | this.endIP = endIP; 27 | this.netMask = netMask; 28 | this.nextIp = ipToLong(startIP); 29 | this.endLongIP = ipToLong(endIP); 30 | } 31 | 32 | public static long ipToLong(String strIp) { 33 | if (StringUtils.isEmpty(strIp)) { 34 | log.error("The given string IP is empty."); 35 | return -1; 36 | } 37 | 38 | long[] ip = new long[4]; 39 | int position1 = strIp.indexOf("."); 40 | int position2 = strIp.indexOf(".", position1 + 1); 41 | int position3 = strIp.indexOf(".", position2 + 1); 42 | ip[0] = Long.parseLong(strIp.substring(0, position1)); 43 | ip[1] = Long.parseLong(strIp.substring(position1 + 1, position2)); 44 | ip[2] = Long.parseLong(strIp.substring(position2 + 1, position3)); 45 | ip[3] = Long.parseLong(strIp.substring(position3 + 1)); 46 | return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; 47 | } 48 | 49 | public static String longToIP(long longIp) { 50 | if (longIp < 0) { 51 | log.error("The given long IP is less than 0."); 52 | return "0.0.0.0"; 53 | } 54 | 55 | StringBuffer sb = new StringBuffer(""); 56 | sb.append(String.valueOf((longIp >>> 24))); 57 | sb.append("."); 58 | sb.append(String.valueOf((longIp & 0x00FFFFFF) >>> 16)); 59 | sb.append("."); 60 | sb.append(String.valueOf((longIp & 0x0000FFFF) >>> 8)); 61 | sb.append("."); 62 | sb.append(String.valueOf((longIp & 0x000000FF))); 63 | return sb.toString(); 64 | } 65 | 66 | public String getNextStringIP() { 67 | String nextStringIP = longToIP(nextIp); 68 | nextIp += 1; 69 | return nextStringIP; 70 | } 71 | 72 | public boolean hasNextIP() { 73 | return nextIp <= endLongIP; 74 | } 75 | 76 | /** 77 | * Reset next IP to the start IP. 78 | */ 79 | public void reset() { 80 | this.nextIp = ipToLong(startIP); 81 | } 82 | 83 | public Integer getRandomIndex() { 84 | return randomIndex; 85 | } 86 | 87 | public void setRandomIndex(Integer randomIndex) { 88 | this.randomIndex = randomIndex; 89 | } 90 | 91 | public String getIpWithMaskBits() { 92 | return ipWithMaskBits; 93 | } 94 | 95 | public void setIpWithMaskBits(String ipWithMaskBits) { 96 | this.ipWithMaskBits = ipWithMaskBits; 97 | } 98 | 99 | public String getStartIP() { 100 | return startIP; 101 | } 102 | 103 | public void setStartIP(String startIP) { 104 | this.startIP = startIP; 105 | nextIp = ipToLong(startIP); 106 | } 107 | 108 | public String getEndIP() { 109 | return endIP; 110 | } 111 | 112 | public void setEndIP(String endIP) { 113 | this.endIP = endIP; 114 | this.endLongIP = ipToLong(endIP); 115 | } 116 | 117 | public String getNetMask() { 118 | return netMask; 119 | } 120 | 121 | public void setNetMask(String netMask) { 122 | this.netMask = netMask; 123 | } 124 | 125 | public long getStartLongIP() { 126 | return startLongIP; 127 | } 128 | 129 | public void setStartLongIP(long startLongIP) { 130 | this.startLongIP = startLongIP; 131 | } 132 | 133 | public long getEndLongIP() { 134 | return endLongIP; 135 | } 136 | 137 | public void setEndLongIP(long endLongIP) { 138 | this.endLongIP = endLongIP; 139 | } 140 | 141 | @Override 142 | public int compareTo(IPSegment o) { 143 | return this.getRandomIndex().compareTo(o.getRandomIndex()); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/EmailReporter.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | import org.apache.commons.mail.DefaultAuthenticator; 4 | import org.apache.commons.mail.Email; 5 | import org.apache.commons.mail.EmailException; 6 | import org.apache.commons.mail.SimpleEmail; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.net.InetAddress; 11 | import java.text.SimpleDateFormat; 12 | import java.util.Date; 13 | 14 | /** 15 | * Created by kevin on 5/31/16. 16 | */ 17 | public class EmailReporter { 18 | private final static Logger log = LoggerFactory.getLogger(EmailReporter.class); 19 | 20 | //TODO 转移到application.properties 21 | // email 配置 22 | private String emailHostName = "smtp.office365.com"; 23 | private int emailSmtpPort = 587; 24 | private String emailAuthUsername = "kaiping.he@maxent-inc.com"; 25 | private String emailAuthPassword = "Maxent-khe"; 26 | private String emailtoList = "381827702@qq.com"; 27 | 28 | 29 | private final static EmailReporter _instance = new EmailReporter(); 30 | private final static long dayMilliseconds = 24 * 60 * 60 * 1000; 31 | private final static long hourMilliseconds = 60 * 60 * 1000; 32 | private final static long minuteMilliseconds = 60 * 1000; 33 | 34 | private final Email email = new SimpleEmail(); 35 | 36 | public static EmailReporter getInstance() { 37 | return _instance; 38 | } 39 | 40 | private EmailReporter() { 41 | try { 42 | init(); 43 | } catch (EmailException e) { 44 | log.error("Faild to initialize the email accounts info."); 45 | } 46 | } 47 | 48 | private void init() throws EmailException { 49 | email.setHostName(emailHostName); 50 | email.setSmtpPort(emailSmtpPort); 51 | email.setAuthenticator(new DefaultAuthenticator( 52 | emailAuthUsername, emailAuthPassword)); 53 | email.setStartTLSEnabled(true); 54 | email.setFrom(emailAuthUsername); 55 | String[] toList = emailtoList.split("\\|"); 56 | for (String to : toList) { 57 | email.addTo(to); 58 | } 59 | 60 | email.setSubject("代理服务器IP扫描报告"); 61 | } 62 | 63 | public void report(String scanTarget, Date startTime, long totalIPNum, int portNum, long proxyIPNum, long consumedTime) { 64 | String startTimeStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTime); 65 | 66 | StringBuilder consumedTimeStr = new StringBuilder(); 67 | if (consumedTime >= dayMilliseconds) { 68 | long days = consumedTime / dayMilliseconds; 69 | consumedTimeStr.append(days); 70 | consumedTimeStr.append("天"); 71 | } 72 | 73 | if (consumedTime >= hourMilliseconds) { 74 | long hours = (consumedTime % dayMilliseconds) / hourMilliseconds; 75 | consumedTimeStr.append(hours); 76 | consumedTimeStr.append("小时"); 77 | } 78 | 79 | if (consumedTime >= minuteMilliseconds) { 80 | long minutes = (consumedTime % hourMilliseconds) / minuteMilliseconds; 81 | consumedTimeStr.append(minutes); 82 | consumedTimeStr.append("分钟"); 83 | } 84 | 85 | long seconds = (consumedTime % minuteMilliseconds) / 1000; 86 | consumedTimeStr.append(seconds); 87 | consumedTimeStr.append("秒"); 88 | 89 | String hostname = "localhost"; 90 | try { 91 | hostname = InetAddress.getLocalHost().getHostName(); 92 | } catch (Exception e) { 93 | log.error("Faild to retrieve the host name of the this server, ex: {}", e); 94 | } 95 | long speed = (totalIPNum * portNum * 1000) / consumedTime; 96 | 97 | StringBuilder msgBuilder = new StringBuilder("扫描服务主机:"); 98 | msgBuilder.append(hostname); 99 | msgBuilder.append("\n扫描目标:"); 100 | msgBuilder.append(scanTarget); 101 | msgBuilder.append("\n开始时间:"); 102 | msgBuilder.append(startTimeStr); 103 | msgBuilder.append("\n扫描IP总数:"); 104 | msgBuilder.append(totalIPNum); 105 | msgBuilder.append("\n扫描端口数:"); 106 | msgBuilder.append(portNum); 107 | msgBuilder.append("\n代理IP数:"); 108 | msgBuilder.append(proxyIPNum); 109 | msgBuilder.append("\n探测速度:"); 110 | msgBuilder.append(speed); 111 | msgBuilder.append(" 次/秒"); 112 | msgBuilder.append("\n共计耗时:"); 113 | msgBuilder.append(consumedTimeStr); 114 | 115 | try { 116 | email.setMsg(msgBuilder.toString()); 117 | email.send(); 118 | } catch (EmailException e) { 119 | log.error("Failed to send email for report the scanning results, ex: {}", e); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | https://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.net.URL; 25 | import java.nio.channels.Channels; 26 | import java.nio.channels.ReadableByteChannel; 27 | import java.util.Properties; 28 | 29 | public class MavenWrapperDownloader { 30 | 31 | /** 32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 33 | */ 34 | private static final String DEFAULT_DOWNLOAD_URL = 35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; 36 | 37 | /** 38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 39 | * use instead of the default one. 40 | */ 41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 42 | ".mvn/wrapper/maven-wrapper.properties"; 43 | 44 | /** 45 | * Path where the maven-wrapper.jar will be saved to. 46 | */ 47 | private static final String MAVEN_WRAPPER_JAR_PATH = 48 | ".mvn/wrapper/maven-wrapper.jar"; 49 | 50 | /** 51 | * Name of the property which should be used to override the default download url for the wrapper. 52 | */ 53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 54 | 55 | public static void main(String args[]) { 56 | System.out.println("- Downloader started"); 57 | File baseDirectory = new File(args[0]); 58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 59 | 60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 61 | // wrapperUrl parameter. 62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 63 | String url = DEFAULT_DOWNLOAD_URL; 64 | if(mavenWrapperPropertyFile.exists()) { 65 | FileInputStream mavenWrapperPropertyFileInputStream = null; 66 | try { 67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 68 | Properties mavenWrapperProperties = new Properties(); 69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 71 | } catch (IOException e) { 72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 73 | } finally { 74 | try { 75 | if(mavenWrapperPropertyFileInputStream != null) { 76 | mavenWrapperPropertyFileInputStream.close(); 77 | } 78 | } catch (IOException e) { 79 | // Ignore ... 80 | } 81 | } 82 | } 83 | System.out.println("- Downloading from: : " + url); 84 | 85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 86 | if(!outputFile.getParentFile().exists()) { 87 | if(!outputFile.getParentFile().mkdirs()) { 88 | System.out.println( 89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 90 | } 91 | } 92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 93 | try { 94 | downloadFileFromURL(url, outputFile); 95 | System.out.println("Done"); 96 | System.exit(0); 97 | } catch (Throwable e) { 98 | System.out.println("- Error downloading"); 99 | e.printStackTrace(); 100 | System.exit(1); 101 | } 102 | } 103 | 104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 105 | URL website = new URL(urlString); 106 | ReadableByteChannel rbc; 107 | rbc = Channels.newChannel(website.openStream()); 108 | FileOutputStream fos = new FileOutputStream(destination); 109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 110 | fos.close(); 111 | rbc.close(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /proxy-grab/src/main/java/com/noisy/utils/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.noisy.utils; 2 | 3 | import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; 4 | import com.baomidou.mybatisplus.core.toolkit.StringPool; 5 | import com.baomidou.mybatisplus.generator.AutoGenerator; 6 | import com.baomidou.mybatisplus.generator.InjectionConfig; 7 | import com.baomidou.mybatisplus.generator.config.*; 8 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; 9 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; 10 | import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; 11 | import org.apache.commons.lang3.StringUtils; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Scanner; 16 | 17 | /** 18 | * @Auther: liuzhaoce 19 | * @Date: 2019-04-29 10:44 20 | * @Description: 21 | */ 22 | // 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中 23 | public class CodeGenerator { 24 | 25 | /** 26 | *

27 | * 读取控制台内容 28 | *

29 | */ 30 | public static String scanner(String tip) { 31 | Scanner scanner = new Scanner(System.in); 32 | StringBuilder help = new StringBuilder(); 33 | help.append("请输入" + tip + ":"); 34 | System.out.println(help.toString()); 35 | if (scanner.hasNext()) { 36 | String ipt = scanner.next(); 37 | if (StringUtils.isNotEmpty(ipt)) { 38 | return ipt; 39 | } 40 | } 41 | throw new MybatisPlusException("请输入正确的" + tip + "!"); 42 | } 43 | 44 | public static void main(String[] args) { 45 | // 代码生成器 46 | AutoGenerator mpg = new AutoGenerator(); 47 | 48 | // 全局配置 49 | GlobalConfig gc = new GlobalConfig(); 50 | String projectPath = System.getProperty("user.dir"); 51 | gc.setOutputDir(projectPath + "/proxy-grab/src/main/java"); 52 | gc.setAuthor("liuzhaoce"); 53 | gc.setOpen(false); 54 | // gc.setSwagger2(true); 实体属性 Swagger2 注解 55 | mpg.setGlobalConfig(gc); 56 | 57 | // 数据源配置 58 | DataSourceConfig dsc = new DataSourceConfig(); 59 | dsc.setUrl("jdbc:mysql://localhost:3306/proxy_grab?characterEncoding=utf-8&autoReconnect=true&useSSL=false"); 60 | // dsc.setSchemaName("public"); 61 | dsc.setDriverName("com.mysql.cj.jdbc.Driver"); 62 | dsc.setUsername("root"); 63 | dsc.setPassword("2244363365lzhce&"); 64 | mpg.setDataSource(dsc); 65 | 66 | // 包配置 67 | PackageConfig pc = new PackageConfig(); 68 | // pc.setModuleName(scanner("模块名")); 69 | pc.setParent("com.noisy"); 70 | mpg.setPackageInfo(pc); 71 | 72 | // 自定义配置 73 | InjectionConfig cfg = new InjectionConfig() { 74 | @Override 75 | public void initMap() { 76 | // to do nothing 77 | } 78 | }; 79 | 80 | // 如果模板引擎是 freemarker 81 | String templatePath = "/templates/mapper.xml.ftl"; 82 | // 如果模板引擎是 velocity 83 | // String templatePath = "/templates/mapper.xml.vm"; 84 | 85 | // 自定义输出配置 86 | List focList = new ArrayList<>(); 87 | // 自定义配置会被优先输出 88 | focList.add(new FileOutConfig(templatePath) { 89 | @Override 90 | public String outputFile(TableInfo tableInfo) { 91 | // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!! 92 | return projectPath + "/proxy-grab/src/main/resources/mapper/" 93 | + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; 94 | } 95 | }); 96 | /* 97 | cfg.setFileCreate(new IFileCreate() { 98 | @Override 99 | public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) { 100 | // 判断自定义文件夹是否需要创建 101 | checkDir("调用默认方法创建的目录"); 102 | return false; 103 | } 104 | }); 105 | */ 106 | cfg.setFileOutConfigList(focList); 107 | mpg.setCfg(cfg); 108 | 109 | // 配置模板 110 | TemplateConfig templateConfig = new TemplateConfig(); 111 | 112 | // 配置自定义输出模板 113 | //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别 114 | // templateConfig.setEntity("templates/entity2.java"); 115 | // templateConfig.setService(); 116 | // templateConfig.setController(); 117 | 118 | templateConfig.setXml(null); 119 | mpg.setTemplate(templateConfig); 120 | 121 | // 策略配置 122 | StrategyConfig strategy = new StrategyConfig(); 123 | strategy.setNaming(NamingStrategy.underline_to_camel); 124 | strategy.setColumnNaming(NamingStrategy.underline_to_camel); 125 | strategy.setEntityLombokModel(true); 126 | strategy.setRestControllerStyle(true); 127 | strategy.setInclude(scanner("表名,多个英文逗号分割").split(",")); 128 | strategy.setSuperEntityColumns("id"); 129 | strategy.setControllerMappingHyphenStyle(true); 130 | strategy.setTablePrefix(pc.getModuleName() + "_"); 131 | mpg.setStrategy(strategy); 132 | mpg.setTemplateEngine(new FreemarkerTemplateEngine()); 133 | mpg.execute(); 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | pom 5 | 6 | proxy-kidd 7 | phantom-backend 8 | proxy-grab 9 | phantom-master 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 2.1.4.RELEASE 15 | 16 | 17 | com.noisy 18 | phantom 19 | 0.0.1-SNAPSHOT 20 | phantom 21 | Demo project for Spring Boot 22 | 23 | 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | com.noisy 31 | proxy-kidd 32 | ${project.version} 33 | 34 | 35 | com.noisy 36 | phantom-backend 37 | ${project.version} 38 | 39 | 40 | com.noisy 41 | proxy-grab 42 | ${project.version} 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-data-jpa 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter 55 | 56 | 57 | 58 | 59 | com.baomidou 60 | mybatis-plus 61 | 3.1.1 62 | 63 | 64 | 65 | org.springframework 66 | spring-web 67 | 5.1.6.RELEASE 68 | 69 | 70 | 71 | com.baomidou 72 | mybatis-plus-boot-starter 73 | 3.1.1 74 | 75 | 76 | junit 77 | junit 78 | 4.10 79 | 80 | 81 | 82 | org.springframework.boot 83 | spring-boot-test 84 | 2.0.3.RELEASE 85 | 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-starter-web 91 | 92 | 93 | org.projectlombok 94 | lombok 95 | true 96 | 97 | 98 | org.springframework.boot 99 | spring-boot-starter-test 100 | test 101 | 102 | 103 | commons-configuration 104 | commons-configuration 105 | 1.9 106 | 107 | 108 | commons-io 109 | commons-io 110 | 2.6 111 | 112 | 113 | org.apache.commons 114 | commons-lang3 115 | 3.8.1 116 | 117 | 118 | 119 | io.netty 120 | netty-all 121 | 4.1.35.Final 122 | 123 | 124 | org.apache.commons 125 | commons-email 126 | 1.4 127 | 128 | 129 | us.monoid.web 130 | resty 131 | 0.3.2 132 | 133 | 134 | cn.wanghaomiao 135 | SeimiCrawler 136 | 2.1.1 137 | 138 | 139 | 140 | com.virjar 141 | sipsoup 142 | RELEASE 143 | 144 | 145 | 146 | com.baomidou 147 | mybatis-plus-generator 148 | 3.1.1 149 | 150 | 151 | 152 | 153 | org.freemarker 154 | freemarker 155 | 2.3.28 156 | 157 | 158 | 159 | 160 | com.alibaba 161 | druid 162 | 1.1.10 163 | 164 | 165 | 166 | 167 | mysql 168 | mysql-connector-java 169 | 5.1.40 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | org.springframework.boot 178 | spring-boot-maven-plugin 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( 125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | echo Found %WRAPPER_JAR% 132 | ) else ( 133 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 134 | echo Downloading from: %DOWNLOAD_URL% 135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" 136 | echo Finished downloading %WRAPPER_JAR% 137 | ) 138 | @REM End of extension 139 | 140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 141 | if ERRORLEVEL 1 goto error 142 | goto end 143 | 144 | :error 145 | set ERROR_CODE=1 146 | 147 | :end 148 | @endlocal & set ERROR_CODE=%ERROR_CODE% 149 | 150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 154 | :skipRcPost 155 | 156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 158 | 159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 160 | 161 | exit /B %ERROR_CODE% 162 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/TaskScheduler.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | import com.noisy.proxy.detector.ProxyDetector; 4 | import com.noisy.proxy.detector.ProxyDetectorFactory; 5 | import com.noisy.proxy.entity.InputType; 6 | import com.noisy.proxy.entity.ProtocolType; 7 | import com.noisy.proxy.util.IPFilterUtils; 8 | import com.noisy.proxy.util.IPPoolUtils; 9 | import com.noisy.proxy.util.IPSegment; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.util.Iterator; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | /** 20 | * Created by kevin on 5/25/16. 21 | */ 22 | 23 | public class TaskScheduler implements Runnable { 24 | 25 | 26 | private final static Logger log = LoggerFactory.getLogger(TaskScheduler.class); 27 | 28 | private Set ports; 29 | private String name; 30 | private String scanTarget; 31 | private Map ipSegments; 32 | private Set ipList; 33 | private ProtocolType protocolType; 34 | private ProxyDetector proxyDetector; 35 | private long totalTasks; 36 | private String inputType; 37 | 38 | public TaskScheduler(String name, String scanTarget, ProtocolType protocolType, Map ipSegments,Set ports) { 39 | if (StringUtils.isEmpty(name) || StringUtils.isEmpty(scanTarget) 40 | || protocolType == null || ipSegments == null) { 41 | throw new IllegalArgumentException( 42 | "Any one of the parameters cannot be null when constructing the TaskScheduler."); 43 | } 44 | log.info("Building scheduler: {}", name); 45 | this.name = name; 46 | this.scanTarget = scanTarget; 47 | this.protocolType = protocolType; 48 | this.ipSegments = ipSegments; 49 | this.ports = ports; 50 | 51 | proxyDetector = ProxyDetectorFactory.createProxyDetector(protocolType, this); 52 | totalTasks = 0; 53 | inputType = InputType.IP_SEGMENTS.getType(); 54 | } 55 | 56 | public TaskScheduler(String name, String scanTarget, ProtocolType protocolType, Set ipList,Set ports) { 57 | if (StringUtils.isEmpty(name) || StringUtils.isEmpty(scanTarget) 58 | || protocolType == null || ipList == null) { 59 | throw new IllegalArgumentException( 60 | "Any one of the parameters cannot be null when constructing the TaskScheduler."); 61 | } 62 | log.info("Building scheduler: {}", name); 63 | this.name = name; 64 | this.scanTarget = scanTarget; 65 | this.protocolType = protocolType; 66 | this.ipList = ipList; 67 | this.ports = ports; 68 | 69 | proxyDetector = ProxyDetectorFactory.createProxyDetector(protocolType, this); 70 | totalTasks = 0; 71 | inputType = InputType.IP_LIST.getType(); 72 | } 73 | 74 | @Override 75 | public void run() { 76 | proxyDetector.reset(); 77 | log.info("The scheduler {} started to execute the new schedule with {} input.", name, inputType); 78 | if (InputType.IP_LIST.isThisType(inputType)) { 79 | createTaskFromIpList(); 80 | } else { 81 | createTaskFromIpSegs(); 82 | } 83 | } 84 | 85 | private void createTaskFromIpSegs() { 86 | if (ipSegments == null || ipSegments.isEmpty()) { 87 | return ; 88 | } 89 | //TODO 计算量太大 90 | // countTotalTasks(); 91 | 92 | log.info("{}: creating tasks.", name); 93 | for (Integer port : ports) { 94 | List ipSegmentList = IPPoolUtils.getIPSegments(ipSegments.values()); 95 | while (!ipSegmentList.isEmpty()) { 96 | Iterator iterator = ipSegmentList.iterator(); 97 | while (iterator.hasNext()) { 98 | IPSegment ipSegment = iterator.next(); 99 | if (ipSegment.hasNextIP()) { 100 | String proxyIP = ipSegment.getNextStringIP(); 101 | if (!IPFilterUtils.getInstance().needFilter(proxyIP)) { 102 | proxyDetector.detect(proxyIP, port); 103 | log.info("proxy detect start...proxyIP:{} ### port:{}",proxyIP,port); 104 | } 105 | } else { 106 | iterator.remove(); 107 | } 108 | } 109 | } 110 | } 111 | 112 | // long totalIPNum = totalTasks / ports.size(); 113 | // log.info("{} has finished to create the tasks, total IP number: {}", name, totalIPNum); 114 | 115 | } 116 | 117 | private long createTaskFromIpList() { 118 | countTotalTasks(); 119 | 120 | log.info("{}: creating tasks.", name); 121 | for (Integer port : ports) { 122 | for (String proxyIP : ipList) { 123 | 124 | proxyDetector.detect(proxyIP, port); 125 | log.info("proxy detect start...proxyIP:{} ### port:{}",proxyIP,port); 126 | } 127 | } 128 | 129 | long totalIPNum = totalTasks / ports.size(); 130 | log.info("{} has finished to create the tasks, total IP number: {}", name, totalIPNum); 131 | 132 | return totalTasks; 133 | } 134 | 135 | public long countTotalTasks() { 136 | if (totalTasks > 0) { 137 | return totalTasks; 138 | } 139 | 140 | log.info("Counting tasks."); 141 | if (InputType.IP_LIST.isThisType(inputType)) { 142 | totalTasks = ports.size() * (ipList == null ? 0 : ipList.size()); 143 | } else { 144 | for (int i = 0; i < ports.size(); i++) { 145 | List ipSegmentList = IPPoolUtils.getIPSegments(ipSegments.values()); 146 | while (!ipSegmentList.isEmpty()) { 147 | Iterator iterator = ipSegmentList.iterator(); 148 | while (iterator.hasNext()) { 149 | IPSegment ipSegment = iterator.next(); 150 | if (ipSegment.hasNextIP()) { 151 | String proxyIP = ipSegment.getNextStringIP(); 152 | if (!IPFilterUtils.getInstance().needFilter(proxyIP)) { 153 | totalTasks++; 154 | } 155 | } else { 156 | iterator.remove(); 157 | } 158 | } 159 | } 160 | } 161 | } 162 | log.info("Total tasks: {}", totalTasks); 163 | 164 | return totalTasks; 165 | } 166 | 167 | public String getName() { 168 | return name; 169 | } 170 | 171 | public String getScanTarget() { 172 | return scanTarget; 173 | } 174 | 175 | public void setScanTarget(String scanTarget) { 176 | this.scanTarget = scanTarget; 177 | } 178 | 179 | public Map getIpSegments() { 180 | return ipSegments; 181 | } 182 | 183 | public ProtocolType getProtocolType() { 184 | return protocolType; 185 | } 186 | 187 | public void setProtocolType(ProtocolType protocolType) { 188 | this.protocolType = protocolType; 189 | } 190 | 191 | public int getScanPortNum() { 192 | return ports.size(); 193 | } 194 | 195 | public ProxyDetector getProxyDetector() { 196 | return proxyDetector; 197 | } 198 | 199 | public long getTotalTasks() { 200 | return totalTasks; 201 | } 202 | 203 | public void setTotalTasks(long totalTasks) { 204 | this.totalTasks = totalTasks; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | ########################################################################################## 204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 205 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 206 | ########################################################################################## 207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 208 | if [ "$MVNW_VERBOSE" = true ]; then 209 | echo "Found .mvn/wrapper/maven-wrapper.jar" 210 | fi 211 | else 212 | if [ "$MVNW_VERBOSE" = true ]; then 213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 214 | fi 215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 216 | while IFS="=" read key value; do 217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 218 | esac 219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 220 | if [ "$MVNW_VERBOSE" = true ]; then 221 | echo "Downloading from: $jarUrl" 222 | fi 223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 224 | 225 | if command -v wget > /dev/null; then 226 | if [ "$MVNW_VERBOSE" = true ]; then 227 | echo "Found wget ... using wget" 228 | fi 229 | wget "$jarUrl" -O "$wrapperJarPath" 230 | elif command -v curl > /dev/null; then 231 | if [ "$MVNW_VERBOSE" = true ]; then 232 | echo "Found curl ... using curl" 233 | fi 234 | curl -o "$wrapperJarPath" "$jarUrl" 235 | else 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Falling back to using Java to download" 238 | fi 239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 240 | if [ -e "$javaClass" ]; then 241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 242 | if [ "$MVNW_VERBOSE" = true ]; then 243 | echo " - Compiling MavenWrapperDownloader.java ..." 244 | fi 245 | # Compiling the Java class 246 | ("$JAVA_HOME/bin/javac" "$javaClass") 247 | fi 248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 249 | # Running the downloader 250 | if [ "$MVNW_VERBOSE" = true ]; then 251 | echo " - Running MavenWrapperDownloader.java ..." 252 | fi 253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 254 | fi 255 | fi 256 | fi 257 | fi 258 | ########################################################################################## 259 | # End of extension 260 | ########################################################################################## 261 | 262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 263 | if [ "$MVNW_VERBOSE" = true ]; then 264 | echo $MAVEN_PROJECTBASEDIR 265 | fi 266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 267 | 268 | # For Cygwin, switch paths to Windows format before running java 269 | if $cygwin; then 270 | [ -n "$M2_HOME" ] && 271 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 272 | [ -n "$JAVA_HOME" ] && 273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 274 | [ -n "$CLASSPATH" ] && 275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 276 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 278 | fi 279 | 280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 281 | 282 | exec "$JAVACMD" \ 283 | $MAVEN_OPTS \ 284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 287 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/HTTPProxyDetector.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | import com.noisy.proxy.TaskScheduler; 4 | import com.noisy.proxy.dao.ProxyInfoDao; 5 | import com.noisy.proxy.dao.ProxyInfoDaoFilempl; 6 | import com.noisy.proxy.entity.ProtocolType; 7 | import com.noisy.proxy.entity.ProxyInfo; 8 | import com.noisy.proxy.entity.ProxyType; 9 | import io.netty.bootstrap.Bootstrap; 10 | import io.netty.buffer.ByteBuf; 11 | import io.netty.channel.*; 12 | import io.netty.channel.nio.NioEventLoopGroup; 13 | import io.netty.channel.socket.nio.NioSocketChannel; 14 | import io.netty.handler.codec.http.*; 15 | import io.netty.handler.timeout.ReadTimeoutHandler; 16 | import io.netty.handler.timeout.WriteTimeoutHandler; 17 | import io.netty.util.AttributeKey; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.io.File; 22 | import java.net.URI; 23 | import java.util.Calendar; 24 | import java.util.concurrent.Semaphore; 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.atomic.AtomicLong; 27 | 28 | /** 29 | * Created by lei.x on 5/24/19. 30 | */ 31 | public class HTTPProxyDetector extends AbstractProxyDetector { 32 | private static final Logger log = LoggerFactory.getLogger(HTTPProxyDetector.class); 33 | // 线程池核心数 Config the thread pool size by the multiple of the CPU cores, must small than 20 34 | private final static int THREAD_POOL_SIZE_CORES_MULTIPLE = 2; 35 | private final static int nThreads = THREAD_POOL_SIZE_CORES_MULTIPLE 36 | * Runtime.getRuntime().availableProcessors(); 37 | 38 | private final ProxyInfoDao proxyInfoDao = new ProxyInfoDaoFilempl(); 39 | 40 | private EventLoopGroup workerGroup; 41 | private Calendar startTime = Calendar.getInstance(); 42 | private final AtomicLong taskCounter = new AtomicLong(0); 43 | private final AtomicLong totalTasks = new AtomicLong(0); 44 | private final AtomicLong proxyIPNum = new AtomicLong(0); 45 | // The TCP connection limits of the system, must small than 500000 46 | private final int tcpConnLimits = 32000; 47 | private final Semaphore semaphore = new Semaphore(tcpConnLimits); 48 | private final Semaphore canStartNextSchSem = new Semaphore(1); 49 | private Bootstrap bootstrap; 50 | private String outputTmpFilePath; 51 | private File outputTmpFile; 52 | private TaskScheduler scheduler; 53 | 54 | public HTTPProxyDetector(TaskScheduler scheduler) { 55 | this.scheduler = scheduler; 56 | workerGroup = new NioEventLoopGroup(nThreads); 57 | 58 | bootstrap = new Bootstrap(); 59 | bootstrap.group(workerGroup); 60 | bootstrap.channel(NioSocketChannel.class); 61 | bootstrap.option(ChannelOption.AUTO_CLOSE, true); 62 | bootstrap.option(ChannelOption.SO_REUSEADDR, true); 63 | bootstrap.option(ChannelOption.TCP_NODELAY, true); 64 | bootstrap.option(ChannelOption.SO_KEEPALIVE, false); 65 | bootstrap.option(ChannelOption.SO_SNDBUF, 1024); 66 | bootstrap.option(ChannelOption.SO_RCVBUF, 4096); 67 | bootstrap.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator()); 68 | bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout()); 69 | 70 | 71 | bootstrap.handler(new ChannelInitializer() { 72 | @Override 73 | public void initChannel(NioSocketChannel ch) throws Exception { 74 | // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码 75 | ch.pipeline().addLast(new HttpClientCodec()); 76 | ch.pipeline().addLast(new ReadTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 77 | ch.pipeline().addLast(new HttpClientOutboundHandler()); 78 | ch.pipeline().addLast(new WriteTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 79 | // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码 80 | // ch.pipeline().addLast(new HttpRequestEncoder()); 81 | 82 | ch.pipeline().addLast(new HTTPProxyRespHandler()); 83 | } 84 | }); 85 | 86 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 87 | outputTmpFile = new File(outputTmpFilePath); 88 | if (!outputTmpFile.getParentFile().exists()) { 89 | outputTmpFile.getParentFile().mkdirs(); 90 | } 91 | } 92 | 93 | public void reset() { 94 | try { 95 | canStartNextSchSem.acquire(); 96 | } catch (InterruptedException e) { 97 | log.error("An exception occurred when resetting the HTTP proxy detector, ex: {}", e); 98 | } 99 | startTime.setTimeInMillis(System.currentTimeMillis()); 100 | totalTasks.set(taskCounter.get()); 101 | proxyIPNum.set(0); 102 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 103 | outputTmpFile = new File(outputTmpFilePath); 104 | if (!outputTmpFile.getParentFile().exists()) { 105 | outputTmpFile.getParentFile().mkdirs(); 106 | } 107 | } 108 | 109 | @Override 110 | public void detect(String ip, int port) { 111 | try { 112 | semaphore.acquire(); 113 | log.info("semaphore acquire:{}", semaphore.toString()); 114 | } catch (InterruptedException e) { 115 | log.warn("An exception occurred when creating a detection task, ex: {}", e); 116 | } 117 | 118 | // Start the client. 119 | try { 120 | ChannelFuture f = bootstrap.connect(ip, port); 121 | f.channel().attr(AttributeKey.valueOf("ip")).set(ip); 122 | f.channel().attr(AttributeKey.valueOf("port")).set(port); 123 | 124 | long leftTasks = taskCounter.get(); 125 | long tmpTotalTasks = totalTasks.incrementAndGet(); 126 | 127 | 128 | // if (((tmpTotalTasks == scheduler.getTotalTasks()) && (leftTasks % 100) == 0) 129 | // || ((tmpTotalTasks % 1000000) == 0)) { 130 | // log.info("Created tasks: {}, Left tasks: {}", tmpTotalTasks, leftTasks); 131 | // } 132 | } catch (Exception e) { 133 | log.error("An exception occurred when connecting to host {}:{}, ex: {}", ip, port, e); 134 | } 135 | } 136 | 137 | private synchronized void finish(ChannelHandlerContext ctx) throws InterruptedException { 138 | // 避免重复调用 139 | if (ctx.channel().hasAttr(AttributeKey.valueOf("finished"))) { 140 | return; 141 | } 142 | 143 | semaphore.release(); 144 | log.info("semaphore release:{}", semaphore.toString()); 145 | ctx.channel().attr(AttributeKey.valueOf("finished")).set(true); 146 | 147 | long leftTasks = taskCounter.decrementAndGet(); 148 | if (leftTasks < 1) { 149 | log.info("Total tasks: {}, Left tasks: {}", totalTasks, taskCounter); 150 | canStartNextSchSem.release(); 151 | 152 | long consumedTime = System.currentTimeMillis() - startTime.getTimeInMillis(); 153 | // EmailReporter.getInstance().report(scheduler.getScanTarget(), 154 | // startTime.getTime(), totalTasks.get() / scheduler.getScanPortNum(), 155 | // scheduler.getScanPortNum(), proxyIPNum.get(), consumedTime); 156 | 157 | log.info("Finished one scanning schedule, total tasks: {}, consumed time: {},file address:{}", 158 | totalTasks, consumedTime, outputTmpFile.getPath()); 159 | } 160 | } 161 | 162 | private class HTTPProxyRespHandler extends ChannelInboundHandlerAdapter { 163 | 164 | @Override 165 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 166 | String responseText; 167 | if (msg instanceof HttpContent) { 168 | HttpContent content = (HttpContent) msg; 169 | ByteBuf buf = content.content(); 170 | responseText = buf.toString(io.netty.util.CharsetUtil.UTF_8); 171 | buf.release(); 172 | 173 | String proxyIP = (String) ctx.channel().attr(AttributeKey.valueOf("ip")).get(); 174 | ProxyType proxyType = checkProxyType(proxyIP, responseText.trim()); 175 | if (proxyType != null) { 176 | ProxyInfo proxyInfo; 177 | Integer port = (Integer) ctx.channel().attr(AttributeKey.valueOf("port")).get(); 178 | proxyInfo = new ProxyInfo(proxyIP, 179 | ProtocolType.HTTP.getType(), port, proxyType.getType(), System.currentTimeMillis()); 180 | log.info("FIND PROXY:" + proxyInfo.toString()); 181 | proxyIPNum.incrementAndGet(); 182 | //TODO 添加GEO数据库 183 | // proxyInfo.setLocation(IPLocationUtils.getLocation(proxyInfo.getIp())); 184 | proxyInfoDao.append(proxyInfo, outputTmpFile); 185 | } 186 | } 187 | 188 | finish(ctx); 189 | ctx.channel().close(); 190 | } 191 | 192 | @Override 193 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 194 | // Send HTTP request 195 | URI uri = new URI(getProxyCheckerURL()); 196 | int port = uri.getPort(); 197 | String host = uri.getHost() + ":" + String.valueOf(port); 198 | 199 | HttpRequest request = new DefaultHttpRequest( 200 | HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath()); 201 | request.headers().set(HttpHeaderNames.HOST, host); 202 | request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE); 203 | request.headers().set(HttpHeaderNames.PROXY_CONNECTION, HttpHeaderValues.KEEP_ALIVE); 204 | 205 | 206 | ctx.channel().writeAndFlush(request); 207 | } 208 | 209 | @Override 210 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 211 | finish(ctx); 212 | ctx.fireChannelInactive(); 213 | } 214 | 215 | @Override 216 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 217 | finish(ctx); 218 | ctx.channel().close(); 219 | } 220 | 221 | @Override 222 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 223 | taskCounter.incrementAndGet(); 224 | ctx.fireChannelRegistered(); 225 | } 226 | 227 | @Override 228 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 229 | finish(ctx); 230 | ctx.fireChannelUnregistered(); 231 | } 232 | } 233 | 234 | private class HttpClientOutboundHandler extends ChannelOutboundHandlerAdapter { 235 | @Override 236 | public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { 237 | finish(ctx); 238 | ctx.close(promise); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/util/IPPoolUtils.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.util; 2 | 3 | import com.noisy.proxy.ProxyScanner; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.*; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | /** 13 | * Created by kevin on 5/25/16. 14 | */ 15 | public class IPPoolUtils { 16 | private final static Logger log = LoggerFactory.getLogger(IPPoolUtils.class); 17 | private static final Pattern PATTERN = Pattern.compile( 18 | "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); 19 | private final static Pattern ipreg = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); 20 | 21 | public static Set retrieveIPFromText(String text) { 22 | if (text == null) { 23 | return null; 24 | } 25 | 26 | Matcher matcher = ipreg.matcher(text); 27 | Set ipSet = new HashSet<>(); 28 | while (matcher.find()) { 29 | ipSet.add(matcher.group()); 30 | } 31 | 32 | return ipSet; 33 | } 34 | 35 | public static boolean validateIP(final String ip) { 36 | return PATTERN.matcher(ip).matches(); 37 | } 38 | 39 | /** 40 | * Get IPSegments from a normal IP segment expression list, IP with mask bits, eg. 220.154.0.0/15 41 | * 42 | * @param ipWithMaskBitsList 43 | * @return 44 | */ 45 | public static List getIPSegments(Collection ipWithMaskBitsList) { 46 | if (ipWithMaskBitsList == null) { 47 | throw new IllegalArgumentException("The given IP segment expression list is null."); 48 | } 49 | Random random = new Random(System.currentTimeMillis()); 50 | 51 | List ipSegments = new ArrayList<>(); 52 | for (String ipWithMaskBits : ipWithMaskBitsList) { 53 | IPSegment ipSegment = getIPSegment(ipWithMaskBits); 54 | ipSegment.setRandomIndex(random.nextInt()); 55 | //ipSegment.setIpWithMaskBits(ipWithMaskBits); 56 | if (needAdds(ipSegment, ipSegments)) { 57 | ipSegments.add(ipSegment); 58 | } 59 | } 60 | Collections.sort(ipSegments); 61 | 62 | return ipSegments; 63 | } 64 | 65 | private static boolean needAdds(final IPSegment ipSegment, final List ipSegments) { 66 | Iterator iterator = ipSegments.iterator(); 67 | while (iterator.hasNext()) { 68 | IPSegment segment = iterator.next(); 69 | // if the given IP segment has been include 70 | if (ipSegment.getStartLongIP() >= segment.getStartLongIP() 71 | && ipSegment.getEndLongIP() <= segment.getEndLongIP()) { 72 | return false; 73 | } 74 | 75 | // if the given IP segment include an exists IP segment in the list, then remove the exists one. 76 | if (ipSegment.getStartLongIP() <= segment.getStartLongIP() 77 | && ipSegment.getEndLongIP() >= segment.getEndLongIP()) { 78 | iterator.remove(); 79 | } 80 | } 81 | 82 | return true; 83 | } 84 | 85 | /** 86 | * Get IPSegment from a normal IP segment expression, IP with mask bits, eg. 220.154.0.0/15 87 | * 88 | * @param ipWithMaskBits 89 | * @return 90 | */ 91 | public static IPSegment getIPSegment(String ipWithMaskBits) { 92 | if (StringUtils.isEmpty(ipWithMaskBits)) { 93 | log.error("The given parameter is empty or null."); 94 | return null; 95 | } 96 | 97 | String[] ipSegTmp = ipWithMaskBits.trim().split("\\/"); 98 | if (ipSegTmp.length != 2 || !validateIP(ipSegTmp[0])) { 99 | log.error("The given IP segments expression is invalid."); 100 | return null; 101 | } 102 | 103 | return getEndIP(ipSegTmp[0], Integer.valueOf(ipSegTmp[1])); 104 | } 105 | 106 | /** 107 | * According to the start IP address and the bits number of net mask to calculate the end IP address. 108 | * 109 | * @param startIP 110 | * @param netmask 111 | * @return 112 | */ 113 | public static IPSegment getEndIP(String startIP, int netmask) { 114 | return getEndIP(startIP, getMask(netmask)); 115 | } 116 | 117 | /** 118 | * Return the net mask with the given bits of net mask 119 | * 120 | * @param masks 121 | * @return 122 | */ 123 | public static String getMask(int masks) { 124 | if (masks == 1) 125 | return "128.0.0.0"; 126 | else if (masks == 2) 127 | return "192.0.0.0"; 128 | else if (masks == 3) 129 | return "224.0.0.0"; 130 | else if (masks == 4) 131 | return "240.0.0.0"; 132 | else if (masks == 5) 133 | return "248.0.0.0"; 134 | else if (masks == 6) 135 | return "252.0.0.0"; 136 | else if (masks == 7) 137 | return "254.0.0.0"; 138 | else if (masks == 8) 139 | return "255.0.0.0"; 140 | else if (masks == 9) 141 | return "255.128.0.0"; 142 | else if (masks == 10) 143 | return "255.192.0.0"; 144 | else if (masks == 11) 145 | return "255.224.0.0"; 146 | else if (masks == 12) 147 | return "255.240.0.0"; 148 | else if (masks == 13) 149 | return "255.248.0.0"; 150 | else if (masks == 14) 151 | return "255.252.0.0"; 152 | else if (masks == 15) 153 | return "255.254.0.0"; 154 | else if (masks == 16) 155 | return "255.255.0.0"; 156 | else if (masks == 17) 157 | return "255.255.128.0"; 158 | else if (masks == 18) 159 | return "255.255.192.0"; 160 | else if (masks == 19) 161 | return "255.255.224.0"; 162 | else if (masks == 20) 163 | return "255.255.240.0"; 164 | else if (masks == 21) 165 | return "255.255.248.0"; 166 | else if (masks == 22) 167 | return "255.255.252.0"; 168 | else if (masks == 23) 169 | return "255.255.254.0"; 170 | else if (masks == 24) 171 | return "255.255.255.0"; 172 | else if (masks == 25) 173 | return "255.255.255.128"; 174 | else if (masks == 26) 175 | return "255.255.255.192"; 176 | else if (masks == 27) 177 | return "255.255.255.224"; 178 | else if (masks == 28) 179 | return "255.255.255.240"; 180 | else if (masks == 29) 181 | return "255.255.255.248"; 182 | else if (masks == 30) 183 | return "255.255.255.252"; 184 | else if (masks == 31) 185 | return "255.255.255.254"; 186 | else if (masks == 32) 187 | return "255.255.255.255"; 188 | return ""; 189 | } 190 | 191 | /** 192 | * According to the start IP address and the net mask to calculate the end IP address. 193 | * 194 | * @param startIP 195 | * @param netmask 196 | * @return 197 | */ 198 | public static IPSegment getEndIP(String startIP, String netmask) { 199 | String[] start = Negation(startIP, netmask).split("\\."); 200 | String tmpStartIP = start[0] + "." + start[1] + "." + start[2] + "." + (Integer.valueOf(start[3]) + 1); 201 | String tmpEndIP = TaskOR(Negation(startIP, netmask), netmask); 202 | 203 | return new IPSegment(tmpStartIP, tmpEndIP, netmask); 204 | } 205 | 206 | /** 207 | * Return the negation of the given start IP address and net mask. 208 | * 209 | * @param startIP 210 | * @param netmask 211 | * @return 212 | */ 213 | private static String Negation(String startIP, String netmask) { 214 | String[] temp1 = startIP.trim().split("\\."); 215 | String[] temp2 = netmask.trim().split("\\."); 216 | int[] rets = new int[4]; 217 | for (int i = 0; i < 4; i++) { 218 | rets[i] = Integer.parseInt(temp1[i]) & Integer.parseInt(temp2[i]); 219 | } 220 | return rets[0] + "." + rets[1] + "." + rets[2] + "." + rets[3]; 221 | } 222 | 223 | private static String TaskOR(String StartIP, String netmask) { 224 | String[] temp1 = StartIP.trim().split("\\."); 225 | String[] temp2 = netmask.trim().split("\\."); 226 | int[] rets = new int[4]; 227 | for (int i = 0; i < 4; i++) { 228 | rets[i] = 255 - (Integer.parseInt(temp1[i]) ^ Integer.parseInt(temp2[i])); 229 | } 230 | return rets[0] + "." + rets[1] + "." + rets[2] + "." + (rets[3] - 1); 231 | } 232 | 233 | /** 234 | * Return address pool size by the bits of net mask. 235 | */ 236 | public static int getPoolMax(int netmask) { 237 | if (netmask <= 0 || netmask >= 32) { 238 | return 0; 239 | } 240 | int bits = 32 - netmask; 241 | return (int) Math.pow(2, bits) - 2; 242 | } 243 | 244 | /** 245 | * Convert the net mask to bits of net mask. 246 | */ 247 | public static int getNetMask(String netmarks) { 248 | StringBuffer sbf; 249 | String str; 250 | int inetmask = 0, count = 0; 251 | String[] ipList = netmarks.split("\\."); 252 | for (int n = 0; n < ipList.length; n++) { 253 | sbf = toBin(Integer.parseInt(ipList[n])); 254 | str = sbf.reverse().toString(); 255 | count = 0; 256 | for (int i = 0; i < str.length(); i++) { 257 | i = str.indexOf('1', i); 258 | if (i == -1) { 259 | break; 260 | } 261 | count++; 262 | } 263 | inetmask += count; 264 | } 265 | return inetmask; 266 | } 267 | 268 | private static StringBuffer toBin(int x) { 269 | StringBuffer result = new StringBuffer(); 270 | result.append(x % 2); 271 | x /= 2; 272 | while (x > 0) { 273 | result.append(x % 2); 274 | x /= 2; 275 | } 276 | return result; 277 | } 278 | 279 | 280 | public static void main(String[] args) { 281 | 282 | String filePath = "/Users/xulei2/data/ip_data/InlandIPSegments.txt"; 283 | Map iPSegments = ProxyScanner.readIPSegments(filePath); 284 | List ipSegmentList = IPPoolUtils.getIPSegments(iPSegments.values()); 285 | int count = 0; 286 | while (!ipSegmentList.isEmpty()){ 287 | Iterator iterator = ipSegmentList.iterator(); 288 | while (iterator.hasNext()) { 289 | IPSegment ipSegment = iterator.next(); 290 | if (ipSegment.hasNextIP()) { 291 | String proxyIP = ipSegment.getNextStringIP(); 292 | if (!IPFilterUtils.getInstance().needFilter(proxyIP)) { 293 | log.info("proxy detect start...proxyIP:{} ### {}",proxyIP,count); 294 | count+=1; 295 | } 296 | } else { 297 | iterator.remove(); 298 | } 299 | } 300 | } 301 | 302 | log.info("total proxy count: {}",count); 303 | } 304 | } 305 | 306 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/Socks4ProxyDetector.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | import com.noisy.proxy.TaskScheduler; 4 | import com.noisy.proxy.dao.ProxyInfoDao; 5 | import com.noisy.proxy.dao.ProxyInfoDaoFilempl; 6 | import com.noisy.proxy.entity.ProtocolType; 7 | import com.noisy.proxy.entity.ProxyInfo; 8 | import com.noisy.proxy.entity.ProxyType; 9 | import io.netty.bootstrap.Bootstrap; 10 | import io.netty.buffer.ByteBuf; 11 | import io.netty.channel.*; 12 | import io.netty.channel.nio.NioEventLoopGroup; 13 | import io.netty.channel.socket.SocketChannel; 14 | import io.netty.channel.socket.nio.NioSocketChannel; 15 | import io.netty.handler.codec.http.*; 16 | import io.netty.handler.proxy.Socks4ProxyHandler; 17 | import io.netty.handler.timeout.ReadTimeoutHandler; 18 | import io.netty.handler.timeout.WriteTimeoutHandler; 19 | import io.netty.util.AttributeKey; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.apache.commons.io.FileUtils; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.net.InetSocketAddress; 26 | import java.net.URI; 27 | import java.net.URISyntaxException; 28 | import java.net.UnknownHostException; 29 | import java.nio.charset.Charset; 30 | import java.util.Calendar; 31 | import java.util.concurrent.Semaphore; 32 | import java.util.concurrent.TimeUnit; 33 | import java.util.concurrent.atomic.AtomicLong; 34 | 35 | /** 36 | * @author lei.X 37 | * @date 2019/5/29 38 | */ 39 | @Slf4j 40 | public class Socks4ProxyDetector extends AbstractProxyDetector { 41 | 42 | private final static int THREAD_POOL_SIZE_CORES_MULTIPLE = 2; 43 | private final static int nThreads = THREAD_POOL_SIZE_CORES_MULTIPLE * Runtime.getRuntime().availableProcessors(); 44 | 45 | private final ProxyInfoDao proxyInfoDao = new ProxyInfoDaoFilempl(); 46 | private EventLoopGroup workerGroup; 47 | private Calendar startTime = Calendar.getInstance(); 48 | private final AtomicLong taskCounter = new AtomicLong(0); 49 | private final AtomicLong totalTasks = new AtomicLong(0); 50 | private final AtomicLong proxyIPNum = new AtomicLong(0); 51 | // The TCP connection limits of the system, must small than 500000 52 | private final int tcpConnLimits = 2000; 53 | private final Semaphore semaphore = new Semaphore(tcpConnLimits); 54 | private final Semaphore canStartNextSchSem = new Semaphore(1); 55 | private Bootstrap bootstrap; 56 | private String outputTmpFilePath; 57 | private File outputTmpFile; 58 | private TaskScheduler scheduler; 59 | private volatile boolean isReported; 60 | 61 | 62 | public Socks4ProxyDetector(TaskScheduler scheduler) { 63 | this.scheduler = scheduler; 64 | 65 | workerGroup = new NioEventLoopGroup(nThreads); 66 | 67 | 68 | bootstrap = new Bootstrap(); 69 | bootstrap.group(workerGroup); 70 | bootstrap.channel(NioSocketChannel.class); 71 | bootstrap.option(ChannelOption.SO_REUSEADDR, true); 72 | bootstrap.option(ChannelOption.TCP_NODELAY, true); 73 | bootstrap.option(ChannelOption.SO_KEEPALIVE, false); 74 | bootstrap.option(ChannelOption.SO_SNDBUF, 1024); 75 | bootstrap.option(ChannelOption.SO_RCVBUF, 4096); 76 | bootstrap.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator()); 77 | bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout()); 78 | 79 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 80 | outputTmpFile = new File(outputTmpFilePath); 81 | if (!outputTmpFile.getParentFile().exists()) { 82 | outputTmpFile.getParentFile().mkdirs(); 83 | } 84 | 85 | isReported = false; 86 | } 87 | 88 | @Override 89 | public void detect(String ip, int port) { 90 | try { 91 | semaphore.acquire(); 92 | } catch (InterruptedException e) { 93 | log.warn("An exception occurred when creating a detection task, ex: {}", e); 94 | } 95 | 96 | 97 | bootstrap.handler(new ChannelInitializer() { 98 | @Override 99 | public void initChannel(SocketChannel ch) throws Exception { 100 | ChannelPipeline p = ch.pipeline(); 101 | 102 | p.addLast(new HttpClientCodec()); 103 | p.addLast(new HttpContentDecompressor()); 104 | p.addLast(new HttpObjectAggregator(10_485_760)); 105 | p.addLast(new WriteTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 106 | p.addLast(new ReadTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 107 | p.addLast(new HttpClientOutboundHandler()); 108 | p.addLast(new SocksProxyRespHandler()); 109 | p.addFirst(new Socks4ProxyHandler(new InetSocketAddress(ip, port))); 110 | } 111 | }); 112 | 113 | 114 | // Connecting the proxy 115 | try { 116 | ChannelFuture f = bootstrap.connect(ip, port); 117 | f.channel().attr(AttributeKey.valueOf("ip")).set(ip); 118 | f.channel().attr(AttributeKey.valueOf("port")).set(port); 119 | 120 | long leftTasks = taskCounter.get(); 121 | long tmpTotalTasks = totalTasks.incrementAndGet(); 122 | // if (((tmpTotalTasks == scheduler.getTotalTasks()) && (leftTasks % 100) == 0) 123 | // || ((tmpTotalTasks % 1000000) == 0)) { 124 | // log.info("Created tasks: {}, Left tasks: {}", tmpTotalTasks, leftTasks); 125 | // } 126 | } catch (Exception e) { 127 | log.error("An exception occurred when connecting to host {}:{}, ex: {}", ip, port, e); 128 | } 129 | } 130 | 131 | @Override 132 | public void reset() { 133 | try { 134 | canStartNextSchSem.acquire(); 135 | } catch (InterruptedException e) { 136 | log.error("An exception occurred when resetting the Socks4 proxy detector, ex: {}", e); 137 | } 138 | startTime.setTimeInMillis(System.currentTimeMillis()); 139 | totalTasks.set(taskCounter.get()); 140 | proxyIPNum.set(0); 141 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 142 | outputTmpFile = new File(outputTmpFilePath); 143 | if (!outputTmpFile.getParentFile().exists()) { 144 | outputTmpFile.getParentFile().mkdirs(); 145 | } 146 | } 147 | 148 | 149 | private synchronized void finish(ChannelHandlerContext ctx) { 150 | if (ctx.channel().hasAttr(AttributeKey.valueOf("finished"))) { 151 | return; 152 | } 153 | 154 | semaphore.release(); 155 | ctx.channel().attr(AttributeKey.valueOf("finished")).set(true); 156 | 157 | long leftTasks = taskCounter.decrementAndGet(); 158 | if (leftTasks < 1) { 159 | log.info("Total tasks: {}, Left tasks: {}", totalTasks, taskCounter); 160 | canStartNextSchSem.release(); 161 | 162 | long consumedTime = System.currentTimeMillis() - startTime.getTimeInMillis(); 163 | // EmailReporter.getInstance().report(scheduler.getScanTarget(), 164 | // startTime.getTime(), totalTasks.get() / scheduler.getScanPortNum(), 165 | // scheduler.getScanPortNum(), proxyIPNum.get(), consumedTime); 166 | String distFilePath = retrieveOutputFilePath(outputTmpFilePath); 167 | try { 168 | if (outputTmpFile.exists()) 169 | FileUtils.moveFile(outputTmpFile, new File(distFilePath)); 170 | } catch (IOException e) { 171 | log.error("Failed to move the temporary file {} to the dist file {}. Exception: {}", 172 | outputTmpFile.getPath(), distFilePath, e); 173 | } 174 | log.info("Finished one scanning schedule, total tasks: {}, consumed time: {}", 175 | totalTasks, consumedTime); 176 | } 177 | } 178 | 179 | private class SocksProxyRespHandler extends ChannelInboundHandlerAdapter { 180 | 181 | @Override 182 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnknownHostException { 183 | String responseText; 184 | if (msg instanceof FullHttpResponse) { 185 | FullHttpResponse httpResp = (FullHttpResponse) msg; 186 | 187 | 188 | ByteBuf content = httpResp.content(); 189 | responseText = content.toString(Charset.forName("UTF-8")); 190 | } else { 191 | responseText = msg.toString(); 192 | } 193 | String proxyIP = (String) ctx.channel().attr(AttributeKey.valueOf("ip")).get(); 194 | 195 | ProxyType proxyType = checkProxyType(proxyIP, responseText.trim()); 196 | if (proxyType != null) { 197 | ProxyInfo proxyInfo; 198 | Integer port = (Integer) ctx.channel().attr(AttributeKey.valueOf("port")).get(); 199 | proxyInfo = new ProxyInfo(proxyIP, 200 | ProtocolType.SOCKS_V4.getType(), port, proxyType.getType(), System.currentTimeMillis()); 201 | proxyIPNum.incrementAndGet(); 202 | log.info("FIND PROXY:" + proxyInfo.toString()); 203 | // proxyInfo.setLocation(IPLocationUtils.getLocation(proxyInfo.getIp())); 204 | proxyInfoDao.append(proxyInfo, outputTmpFile); 205 | } 206 | 207 | finish(ctx); 208 | ctx.channel().close(); 209 | } 210 | 211 | @Override 212 | public void channelActive(ChannelHandlerContext ctx) { 213 | 214 | // HttpRequest request = new DefaultFullHttpRequest( 215 | // HttpVersion.HTTP_1_0, HttpMethod.GET, getProxyCheckerPath()); 216 | // request.headers().set("Host", getProxyCheckerHost() + ":" + getProxyCheckerPort()); 217 | // ctx.writeAndFlush(request); 218 | 219 | 220 | // Send HTTP request 221 | URI uri = null; 222 | try { 223 | uri = new URI(getProxyCheckerURL()); 224 | } catch (URISyntaxException e) { 225 | log.error(e.getMessage()); 226 | } 227 | int port = uri.getPort(); 228 | String host = uri.getHost() + ":" + String.valueOf(port); 229 | 230 | HttpRequest request = new DefaultHttpRequest( 231 | HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath()); 232 | request.headers().set(HttpHeaderNames.HOST, host); 233 | request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE); 234 | request.headers().set(HttpHeaderNames.PROXY_CONNECTION, HttpHeaderValues.KEEP_ALIVE); 235 | 236 | ctx.channel().writeAndFlush(request); 237 | 238 | } 239 | 240 | @Override 241 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 242 | finish(ctx); 243 | ctx.fireChannelInactive(); 244 | } 245 | 246 | @Override 247 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 248 | ctx.channel().close(); 249 | finish(ctx); 250 | } 251 | 252 | @Override 253 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 254 | taskCounter.incrementAndGet(); 255 | ctx.fireChannelRegistered(); 256 | } 257 | 258 | @Override 259 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 260 | finish(ctx); 261 | ctx.fireChannelUnregistered(); 262 | } 263 | } 264 | 265 | private class HttpClientOutboundHandler extends ChannelOutboundHandlerAdapter { 266 | @Override 267 | public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { 268 | finish(ctx); 269 | ctx.close(promise); 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/ProxyScanner.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy; 2 | 3 | import com.noisy.proxy.entity.InputType; 4 | import com.noisy.proxy.entity.ProtocolType; 5 | import org.apache.commons.io.FileUtils; 6 | import org.apache.commons.io.IOUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.core.env.Environment; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.io.*; 15 | import java.text.DateFormat; 16 | import java.text.ParseException; 17 | import java.text.SimpleDateFormat; 18 | import java.util.*; 19 | import java.util.concurrent.Executors; 20 | import java.util.concurrent.ScheduledExecutorService; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | /** 24 | * @author lei.X 25 | * @date 2019/5/5 26 | */ 27 | 28 | @Component 29 | public class ProxyScanner { 30 | 31 | 32 | private final static Logger log = LoggerFactory.getLogger(ProxyScanner.class); 33 | 34 | private static Map inlandIPSegments; 35 | private static Map abroadIPSegments; 36 | private static Set ipList; 37 | private static Set ports; 38 | 39 | @Autowired 40 | private Environment env; 41 | @Value("${data.address}") 42 | private String dataAddress; 43 | @Value("${input_type}") 44 | // 设定初始类型(选择IP_LIST 还是 IP_SEGMENT) 45 | private String inputType; 46 | 47 | 48 | public void start() { 49 | 50 | 51 | String ipListFilePath = dataAddress + "IpList.txt"; 52 | String inlandFilePath = dataAddress + "InlandIPSegments.txt"; 53 | String abroadIpFilePath = dataAddress + "AbroadIPSegments.txt"; 54 | String portFilePath = env.getProperty("detection.ports.file"); 55 | 56 | 57 | // 扫描控制 58 | long inlandHTTPInterval = Integer.valueOf(env.getProperty("inland.http.scanner.interval")) * 60 * 60 * 1000; 59 | long inlandSocks4Interval = Integer.valueOf(env.getProperty("inland.socks4.scanner.interval")) * 60 * 60 * 1000; 60 | long inlandSocks5Interval = Integer.valueOf(env.getProperty("inland.socks5.scanner.interval")) * 60 * 60 * 1000; 61 | long abroadHTTPInterval = Integer.valueOf(env.getProperty("abroad.http.scanner.interval")) * 60 * 60 * 1000; 62 | long abroadSocks4Interval = Integer.valueOf(env.getProperty("abroad.socks4.scanner.interval")) * 60 * 60 * 1000; 63 | long abroadSocks5Interval = Integer.valueOf(env.getProperty("abroad.socks5.scanner.interval")) * 60 * 60 * 1000; 64 | 65 | 66 | log.info("Starting the scanner."); 67 | ScheduledExecutorService executor = Executors.newScheduledThreadPool(4); 68 | 69 | //读取IP list文件 70 | if (InputType.IP_LIST.isThisType(inputType)) { 71 | ipList = getIpListSet(ipListFilePath); 72 | } else { 73 | inlandIPSegments = readIPSegments(inlandFilePath); 74 | abroadIPSegments = readIPSegments(abroadIpFilePath); 75 | } 76 | // 读取port文件 77 | ports = getPortSet(portFilePath); 78 | 79 | if (inlandHTTPInterval >= 0) { 80 | scheduleInlandHTTPTask(executor, inlandHTTPInterval); 81 | } 82 | 83 | if (inlandSocks4Interval >= 0) { 84 | scheduleInlandSocks4Task(executor,inlandSocks4Interval); 85 | } 86 | 87 | if (inlandSocks5Interval >= 0) { 88 | scheduleInlandSocks5Task(executor,inlandSocks5Interval); 89 | } 90 | 91 | if (InputType.IP_SEGMENTS.isThisType(inputType)) { 92 | if (abroadHTTPInterval >= 0) { 93 | scheduleAbroadHTTPTask(executor,abroadHTTPInterval); 94 | } 95 | 96 | if (abroadSocks4Interval >= 0) { 97 | scheduleAbroadSocks4Task(executor,abroadSocks4Interval); 98 | } 99 | 100 | if (abroadSocks5Interval >= 0) { 101 | scheduleAbroadSocks5Task(executor,abroadSocks5Interval); 102 | } 103 | } 104 | 105 | log.info("Scanner started."); 106 | 107 | } 108 | 109 | 110 | private void scheduleInlandHTTPTask(ScheduledExecutorService executor, long inlandHTTPInterval) { 111 | log.info("Scheduling the inland HTTP proxy scheduler."); 112 | TaskScheduler scheduler = null; 113 | 114 | if (InputType.IP_LIST.isThisType(inputType)) { 115 | scheduler = new TaskScheduler("InlandHTTPProxy", "国内HTTP代理", ProtocolType.HTTP, ipList,ports); 116 | } else { 117 | scheduler = new TaskScheduler("InlandHTTPProxy", "国内HTTP代理", ProtocolType.HTTP, inlandIPSegments,ports); 118 | } 119 | //定义启动时间和启动间隔 120 | executor.scheduleAtFixedRate(scheduler, getInitDelay(inlandHTTPInterval, 121 | Integer.valueOf(env.getProperty("inland.http.scanner.start"))), inlandHTTPInterval, TimeUnit.MILLISECONDS); 122 | } 123 | 124 | 125 | private void scheduleInlandSocks4Task(ScheduledExecutorService executor,long inlandSocks4Interval){ 126 | TaskScheduler scheduler = null; 127 | if (InputType.IP_LIST.isThisType(inputType)) { 128 | scheduler = new TaskScheduler("InlandSocks4Proxy", "国内Socks4代理", 129 | ProtocolType.SOCKS_V4, ipList,ports); 130 | } else { 131 | scheduler = new TaskScheduler("InlandSocks4Proxy", "国内Socks4代理", 132 | ProtocolType.SOCKS_V4, inlandIPSegments,ports); 133 | } 134 | executor.scheduleAtFixedRate(scheduler, getInitDelay(inlandSocks4Interval, 135 | Integer.valueOf(env.getProperty("inland.socks4.scanner.start"))), inlandSocks4Interval, TimeUnit.MILLISECONDS); 136 | } 137 | 138 | private void scheduleInlandSocks5Task(ScheduledExecutorService executor,long inlandSocks5Interval){ 139 | TaskScheduler scheduler = null; 140 | if (InputType.IP_LIST.isThisType(inputType)) { 141 | scheduler = new TaskScheduler("InlandSocks5Proxy", "国内Socks5代理", 142 | ProtocolType.SOCKS_V5, ipList,ports); 143 | } else { 144 | scheduler = new TaskScheduler("InlandSocks5Proxy", "国内Socks5代理", 145 | ProtocolType.SOCKS_V5, inlandIPSegments,ports); 146 | } 147 | executor.scheduleAtFixedRate(scheduler, getInitDelay(inlandSocks5Interval, 148 | Integer.valueOf(env.getProperty("inland.socks5.scanner.start"))), inlandSocks5Interval, TimeUnit.MILLISECONDS); 149 | } 150 | 151 | private void scheduleAbroadHTTPTask(ScheduledExecutorService executor,long abroadHTTPInterval) { 152 | TaskScheduler scheduler = new TaskScheduler("AbroadHTTPProxy", "国外HTTP代理", 153 | ProtocolType.HTTP, abroadIPSegments,ports); 154 | executor.scheduleAtFixedRate(scheduler, getInitDelay(abroadHTTPInterval, 155 | Integer.valueOf(env.getProperty("abroad.http.scanner.start"))), abroadHTTPInterval, TimeUnit.MILLISECONDS); 156 | } 157 | 158 | private void scheduleAbroadSocks4Task(ScheduledExecutorService executor,long abroadSocks4Interval) { 159 | TaskScheduler scheduler = new TaskScheduler("abroadSocks4Proxy", "国外socks4代理", 160 | ProtocolType.SOCKS_V4, abroadIPSegments,ports); 161 | executor.scheduleAtFixedRate(scheduler, getInitDelay(abroadSocks4Interval, 162 | Integer.valueOf(env.getProperty("abroad.socks4.scanner.start"))), abroadSocks4Interval, TimeUnit.MILLISECONDS); 163 | } 164 | 165 | private void scheduleAbroadSocks5Task(ScheduledExecutorService executor,long abroadSocks5Interval) { 166 | TaskScheduler scheduler = new TaskScheduler("abroadSocks5Proxy", "国外socks5代理", 167 | ProtocolType.SOCKS_V5, abroadIPSegments,ports); 168 | executor.scheduleAtFixedRate(scheduler, getInitDelay(abroadSocks5Interval, 169 | Integer.valueOf(env.getProperty("abroad.socks5.scanner.start"))), abroadSocks5Interval, TimeUnit.MILLISECONDS); 170 | } 171 | 172 | 173 | 174 | 175 | public static Map readIPSegments(String ipSegFilePath) { 176 | log.info("Loading IP segments from file: {}", ipSegFilePath); 177 | Map ipSegments = new HashMap<>(); 178 | File file = FileUtils.getFile(ipSegFilePath); 179 | if (file == null) { 180 | log.warn("Cannot load the IP segments from file: {}", ipSegFilePath); 181 | return null; 182 | } 183 | 184 | try { 185 | BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); 186 | List ipSegList = IOUtils.readLines(br); 187 | if (ipSegList != null && !ipSegList.isEmpty()) { 188 | int idx = 1; 189 | for (String ipSeg : ipSegList) { 190 | ipSegments.put(idx, ipSeg); 191 | idx += 1; 192 | } 193 | br.close(); 194 | } else { 195 | log.warn("The IP segments file is empty, file path: {}", ipSegFilePath); 196 | br.close(); 197 | return null; 198 | } 199 | } catch (IOException e) { 200 | log.warn("An exception occurred when loading IP segments from file: {}", ipSegFilePath); 201 | return null; 202 | } 203 | 204 | return ipSegments; 205 | } 206 | 207 | 208 | private static long getInitDelay(long interval, int startHour) { 209 | if (startHour < 0) { 210 | return 0; 211 | } 212 | 213 | if (startHour > 24) { 214 | startHour = startHour % 24; 215 | } 216 | 217 | long initDelay = getTimeMillis(startHour + ":00:00") - System.currentTimeMillis(); 218 | initDelay = initDelay > 0 ? initDelay : interval + initDelay; 219 | 220 | return initDelay; 221 | } 222 | 223 | 224 | private static long getTimeMillis(String time) { 225 | try { 226 | DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); 227 | DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd"); 228 | Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time); 229 | return curDate.getTime(); 230 | } catch (ParseException e) { 231 | e.printStackTrace(); 232 | } 233 | return 0; 234 | } 235 | 236 | // 读取IP list 237 | private Set getIpListSet(String ipListFilePath) { 238 | 239 | Set filterIpList; 240 | 241 | File proxyIPFile = new File(ipListFilePath); 242 | try { 243 | List proxyIPs = FileUtils.readLines(proxyIPFile, "utf-8"); 244 | if (proxyIPs != null) { 245 | filterIpList = new HashSet<>(); 246 | filterIpList.addAll(proxyIPs); 247 | return filterIpList; 248 | 249 | } 250 | } catch (IOException e) { 251 | log.error("Failed to load the IP list file: {}", ipListFilePath); 252 | return null; 253 | } 254 | 255 | if (ipList == null || ipList.isEmpty()) { 256 | log.error("The IP list file is empty: {}", ipListFilePath); 257 | return null; 258 | } 259 | 260 | return null; 261 | } 262 | 263 | private Set getPortSet(String portListFilePath) { 264 | Set filterPortList = new HashSet<>(); 265 | 266 | File portListFile = new File(portListFilePath); 267 | try { 268 | List portList = FileUtils.readLines(portListFile, "utf-8"); 269 | if (portList != null && !portList.isEmpty()) { 270 | for (String port : portList) { 271 | filterPortList.add(Integer.valueOf(port)); 272 | 273 | } 274 | return filterPortList; 275 | } 276 | } catch (IOException e) { 277 | log.error("Failed to load the port list file: {}", portListFilePath); 278 | return null; 279 | } 280 | 281 | if (ipList == null || ipList.isEmpty()) { 282 | log.error("The port list file is empty: {}", portListFilePath); 283 | return null; 284 | } 285 | 286 | return null; 287 | } 288 | 289 | } 290 | -------------------------------------------------------------------------------- /proxy-kidd/src/main/java/com/noisy/proxy/detector/Socks5ProxyDetector.java: -------------------------------------------------------------------------------- 1 | package com.noisy.proxy.detector; 2 | 3 | import com.noisy.proxy.TaskScheduler; 4 | import com.noisy.proxy.dao.ProxyInfoDao; 5 | import com.noisy.proxy.dao.ProxyInfoDaoFilempl; 6 | import com.noisy.proxy.entity.ProtocolType; 7 | import com.noisy.proxy.entity.ProxyInfo; 8 | import com.noisy.proxy.entity.ProxyType; 9 | import io.netty.bootstrap.Bootstrap; 10 | import io.netty.buffer.ByteBuf; 11 | import io.netty.channel.*; 12 | import io.netty.channel.epoll.Epoll; 13 | import io.netty.channel.epoll.EpollChannelOption; 14 | import io.netty.channel.nio.NioEventLoopGroup; 15 | import io.netty.channel.socket.SocketChannel; 16 | import io.netty.channel.socket.nio.NioSocketChannel; 17 | import io.netty.handler.codec.http.*; 18 | import io.netty.handler.proxy.Socks5ProxyHandler; 19 | import io.netty.handler.timeout.ReadTimeoutHandler; 20 | import io.netty.handler.timeout.WriteTimeoutHandler; 21 | import io.netty.util.AttributeKey; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.apache.commons.io.FileUtils; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.net.InetSocketAddress; 28 | import java.net.URI; 29 | import java.net.URISyntaxException; 30 | import java.net.UnknownHostException; 31 | import java.nio.charset.Charset; 32 | import java.util.Calendar; 33 | import java.util.concurrent.Semaphore; 34 | import java.util.concurrent.TimeUnit; 35 | import java.util.concurrent.atomic.AtomicLong; 36 | 37 | /** 38 | * Created by lei.x on 5/24/19. 39 | */ 40 | 41 | @Slf4j 42 | public class Socks5ProxyDetector extends AbstractProxyDetector { 43 | 44 | 45 | private final static int THREAD_POOL_SIZE_CORES_MULTIPLE = 2; 46 | private final static int nThreads = THREAD_POOL_SIZE_CORES_MULTIPLE * Runtime.getRuntime().availableProcessors(); 47 | 48 | private final ProxyInfoDao proxyInfoDao = new ProxyInfoDaoFilempl(); 49 | private EventLoopGroup workerGroup; 50 | private Calendar startTime = Calendar.getInstance(); 51 | private final AtomicLong taskCounter = new AtomicLong(0); 52 | private final AtomicLong totalTasks = new AtomicLong(0); 53 | private final AtomicLong proxyIPNum = new AtomicLong(0); 54 | private final int tcpConnLimits = 2000; 55 | private final Semaphore semaphore = new Semaphore(tcpConnLimits); 56 | private final Semaphore canStartNextSchSem = new Semaphore(1); 57 | private Bootstrap bootstrap; 58 | private String outputTmpFilePath; 59 | private File outputTmpFile; 60 | private TaskScheduler scheduler; 61 | private volatile boolean isReported; 62 | 63 | public Socks5ProxyDetector(TaskScheduler scheduler) { 64 | this.scheduler = scheduler; 65 | 66 | workerGroup = new NioEventLoopGroup(nThreads); 67 | 68 | bootstrap = new Bootstrap(); 69 | bootstrap.group(workerGroup); 70 | bootstrap.channel(NioSocketChannel.class); 71 | bootstrap.option(ChannelOption.SO_REUSEADDR, true); 72 | bootstrap.option(ChannelOption.TCP_NODELAY, true); 73 | bootstrap.option(ChannelOption.SO_KEEPALIVE, false); 74 | bootstrap.option(ChannelOption.SO_SNDBUF, 1024); 75 | bootstrap.option(ChannelOption.SO_RCVBUF, 4096); 76 | bootstrap.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator()); 77 | bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout()); 78 | 79 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 80 | outputTmpFile = new File(outputTmpFilePath); 81 | if (!outputTmpFile.getParentFile().exists()) { 82 | outputTmpFile.getParentFile().mkdirs(); 83 | } 84 | 85 | isReported = false; 86 | } 87 | 88 | public void reset() { 89 | try { 90 | canStartNextSchSem.acquire(); 91 | } catch (InterruptedException e) { 92 | log.error("An exception occurred when resetting the Socks4 proxy detector, ex: {}", e); 93 | } 94 | startTime.setTimeInMillis(System.currentTimeMillis()); 95 | totalTasks.set(taskCounter.get()); 96 | proxyIPNum.set(0); 97 | outputTmpFilePath = getOutputTmpFilePath(scheduler.getName()); 98 | outputTmpFile = new File(outputTmpFilePath); 99 | if (!outputTmpFile.getParentFile().exists()) { 100 | outputTmpFile.getParentFile().mkdirs(); 101 | } 102 | } 103 | 104 | @Override 105 | public void detect(final String ip, final int port) { 106 | try { 107 | semaphore.acquire(); 108 | } catch (InterruptedException e) { 109 | log.warn("An exception occurred when creating a detection task, ex: {}", e); 110 | } 111 | 112 | if (Epoll.isAvailable()) { 113 | bootstrap.handler(new ChannelInitializer() { 114 | @Override 115 | public void initChannel(SocketChannel ch) throws Exception { 116 | ch.config().setOption(EpollChannelOption.SO_REUSEPORT, true); 117 | ChannelPipeline p = ch.pipeline(); 118 | 119 | p.addLast(new HttpClientCodec()); 120 | p.addLast(new HttpContentDecompressor()); 121 | p.addLast(new HttpObjectAggregator(10_485_760)); 122 | p.addLast(new WriteTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 123 | p.addLast(new ReadTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 124 | p.addLast(new HttpClientOutboundHandler()); 125 | p.addLast(new SocksProxyRespHandler()); 126 | p.addFirst(new Socks5ProxyHandler(new InetSocketAddress(ip, port))); 127 | } 128 | }); 129 | } else { 130 | bootstrap.handler(new ChannelInitializer() { 131 | @Override 132 | public void initChannel(SocketChannel ch) throws Exception { 133 | ChannelPipeline p = ch.pipeline(); 134 | 135 | p.addLast(new HttpClientCodec()); 136 | p.addLast(new HttpContentDecompressor()); 137 | p.addLast(new HttpObjectAggregator(10_485_760)); 138 | p.addLast(new WriteTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 139 | p.addLast(new ReadTimeoutHandler(getTimeout(), TimeUnit.MILLISECONDS)); 140 | p.addLast(new HttpClientOutboundHandler()); 141 | p.addLast(new SocksProxyRespHandler()); 142 | p.addFirst(new Socks5ProxyHandler(new InetSocketAddress(ip, port))); 143 | } 144 | }); 145 | } 146 | 147 | // Connecting the proxy 148 | try { 149 | ChannelFuture f = bootstrap.connect(ip, port); 150 | f.channel().attr(AttributeKey.valueOf("ip")).set(ip); 151 | f.channel().attr(AttributeKey.valueOf("port")).set(port); 152 | 153 | long leftTasks = taskCounter.get(); 154 | long tmpTotalTasks = totalTasks.incrementAndGet(); 155 | // if (((tmpTotalTasks == scheduler.getTotalTasks()) && (leftTasks % 100) == 0) 156 | // || ((tmpTotalTasks % 1000000) == 0)) { 157 | // log.info("Created tasks: {}, Left tasks: {}", tmpTotalTasks, leftTasks); 158 | // } 159 | } catch (Exception e) { 160 | log.error("An exception occurred when connecting to host {}:{}, ex: {}", ip, port, e); 161 | } 162 | } 163 | 164 | private synchronized void finish(ChannelHandlerContext ctx) { 165 | if (ctx.channel().hasAttr(AttributeKey.valueOf("finished"))) { 166 | return; 167 | } 168 | 169 | semaphore.release(); 170 | ctx.channel().attr(AttributeKey.valueOf("finished")).set(true); 171 | 172 | long leftTasks = taskCounter.decrementAndGet(); 173 | if (leftTasks < 1) { 174 | log.info("Total tasks: {}, Left tasks: {}", totalTasks, taskCounter); 175 | canStartNextSchSem.release(); 176 | 177 | long consumedTime = System.currentTimeMillis() - startTime.getTimeInMillis(); 178 | String distFilePath = retrieveOutputFilePath(outputTmpFilePath); 179 | try { 180 | if (outputTmpFile.exists()) 181 | FileUtils.moveFile(outputTmpFile, new File(distFilePath)); 182 | } catch (IOException e) { 183 | log.error("Failed to move the temporary file {} to the dist file {}. Exception: {}", 184 | outputTmpFile.getPath(), distFilePath, e); 185 | } 186 | log.info("Finished one scanning schedule, total tasks: {}, consumed time: {}", 187 | totalTasks, consumedTime); 188 | } 189 | } 190 | 191 | private class SocksProxyRespHandler extends ChannelInboundHandlerAdapter { 192 | 193 | @Override 194 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnknownHostException { 195 | String responseText; 196 | if (msg instanceof FullHttpResponse) { 197 | FullHttpResponse httpResp = (FullHttpResponse) msg; 198 | 199 | 200 | ByteBuf content = httpResp.content(); 201 | responseText = content.toString(Charset.forName("UTF-8")); 202 | } else { 203 | responseText = msg.toString(); 204 | } 205 | String proxyIP = (String) ctx.channel().attr(AttributeKey.valueOf("ip")).get(); 206 | 207 | ProxyType proxyType = checkProxyType(proxyIP, responseText.trim()); 208 | if (proxyType != null) { 209 | ProxyInfo proxyInfo; 210 | Integer port = (Integer) ctx.channel().attr(AttributeKey.valueOf("port")).get(); 211 | proxyInfo = new ProxyInfo(proxyIP, 212 | ProtocolType.SOCKS_V5.getType(), port, proxyType.getType(), System.currentTimeMillis()); 213 | proxyIPNum.incrementAndGet(); 214 | log.info("FIND PROXY:" + proxyInfo.toString()); 215 | // proxyInfo.setLocation(IPLocationUtils.getLocation(proxyInfo.getIp())); 216 | proxyInfoDao.append(proxyInfo, outputTmpFile); 217 | } 218 | 219 | finish(ctx); 220 | ctx.channel().close(); 221 | } 222 | 223 | @Override 224 | public void channelActive(ChannelHandlerContext ctx) { 225 | // Send HTTP request 226 | URI uri = null; 227 | try { 228 | uri = new URI(getProxyCheckerURL()); 229 | } catch (URISyntaxException e) { 230 | log.error(e.getMessage()); 231 | } 232 | int port = uri.getPort(); 233 | String host = uri.getHost() + ":" + String.valueOf(port); 234 | 235 | HttpRequest request = new DefaultHttpRequest( 236 | HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath()); 237 | request.headers().set(HttpHeaderNames.HOST, host); 238 | request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE); 239 | request.headers().set(HttpHeaderNames.PROXY_CONNECTION, HttpHeaderValues.KEEP_ALIVE); 240 | 241 | ctx.channel().writeAndFlush(request); 242 | } 243 | 244 | @Override 245 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 246 | finish(ctx); 247 | ctx.fireChannelInactive(); 248 | } 249 | 250 | @Override 251 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 252 | ctx.channel().close(); 253 | finish(ctx); 254 | } 255 | 256 | @Override 257 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 258 | taskCounter.incrementAndGet(); 259 | ctx.fireChannelRegistered(); 260 | } 261 | 262 | @Override 263 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 264 | finish(ctx); 265 | ctx.fireChannelUnregistered(); 266 | } 267 | } 268 | 269 | private class HttpClientOutboundHandler extends ChannelOutboundHandlerAdapter { 270 | @Override 271 | public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { 272 | finish(ctx); 273 | ctx.close(promise); 274 | } 275 | } 276 | } 277 | --------------------------------------------------------------------------------