作者归档:徐承恩

Windows科学计算器妙用2的多少次幂等于1024

面试官经常会问初始容量为1000的HashMap,依次存放1000个元素会不会触发扩容?首先1000这个数不满足2的次幂,与之接近且符合2次幂的数为1024,1024乘以0.75等于768,触发扩容阈值为768所以会触发扩容。计算一个数是2的多少次幂我们用科学计算器来算,毕竟人肉逻辑机还是挺慢的。

2的多少次方等于1024

传统计算器:计算器依次按1024 ÷ 2 然后按=直到结果为1,在这个过程中累计按了多少次=则是2的多少次幂数,这里的结果是2的10次幂为1024。

科学计算器:计算器依次按(1000 log) ÷ (2 log) = 计算结果显示的就是2的多次次幂数,这里的结果是2的10次幂为1024。

 

 

使用docker搭建网盘

开源网盘有非常多可选的方案,我个人觉得cloudreve网盘最符合我的需求因为它足够简单。

创建桥接网络

我的想法是创建一个桥接网络,然后用宿主机的nginx反向代理暴露给公网访问,这样做的好处是宿主机不用开启端口。

docker network create --subnet=192.168.0.0/16 docker-network

部署网盘

$PWD表示你当前命令行所处的路径,我们将命令行切换到docker安装目录的volumes目录下。

cd /var/lib/docker/volumes
# 网盘
docker run -itd \
  --name cloudreve \
  --hostname cloudreve \
  --restart=unless-stopped \
  -e PUID=0 \
  -e PGID=0 \
  -e TZ="Asia/Shanghai" \
  -v $PWD/cloudreve/uploads:/cloudreve/uploads \
  -v $PWD/cloudreve/config:/cloudreve/config \
  -v $PWD/cloudreve/db:/cloudreve/db \
  -v $PWD/cloudreve/avatar:/cloudreve/avatar \
  -v $PWD/cloudreve/downloads:/downloads \
  --net docker-network \
  --ip 172.19.0.6 \
  xavierniu/cloudreve

配置数据库

cloudreve默认使用sqlite,我们改为使用mysql.

[Database]
Type = mysql
Port = 3306
User = <数据库用户名>
Password = <数据库密码>
Host = <这样填docker网络网关地址>
Name = <数据库名>
TablePrefix = cd_
Charset = utf8

 

使用Java实现负载均衡算法

说到负载均衡我们首先会想到Nginx负载均衡策略,在Nginx中支持5种负载均衡策略他们分别是:轮询、加权轮询、ip_hash、fair、url_hash。

概念

负载均衡是将客户端请求访问,通过提前约定好的规则转发给各个server。其中有好几个种经典的算法,下面我们用Java实现这几种算法。

轮询算法

轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。

优点:绝对公平

缺点:无法根据服务器性能去分配,无法合理利用服务器资源。

package com.monkeyjava.learn.basic.robin;

import com.google.common.collect.Lists;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestRound {

    private Integer  index = 0;
    private List<String> ips = Lists.newArrayList("192.168.1.1", "192.168.1.2", "192.168.1.3");


    public String roundRobin(){
        String serverIp;
        synchronized(index){
            if (index >= ips.size()){
                index = 0;
            }
            serverIp= ips.get(index);
            //轮询+1
            index ++;
        }
        return serverIp;
    }

    public static void main(String[] args) {
        TestRound testRoundRobin =new TestRound();
        for (int i=0;i< 10 ;i++){
            String serverIp= testRoundRobin.roundRobin();
            System.out.println(serverIp);
        }
    }
}

输出结果:

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.1

加权轮询法

每个机器接受的连接数量按权重比例进行分配。

该算法是对普通轮询算法的改进,比如你可以设定:第三台机器的处理能力是第一台机器的两倍,那么负载均衡器会把两倍的连接数量分配给第3台机器,轮询可以将请求顺序按照权重分配到后端。

package com.monkeyjava.learn.basic.robin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestWeight {
    private Integer index = 0;
    static Map<String, Integer> ipMap=new HashMap<String, Integer>(16);
    static {
        // 1.map, key-ip,value-权重
        ipMap.put("192.168.1.1", 1);
        ipMap.put("192.168.1.2", 2);
        ipMap.put("192.168.1.3", 4);

    }

    public List<String> getServerIpByWeight() {
        List<String> ips = new ArrayList<String>(32);
        for (Map.Entry<String, Integer> entry : ipMap.entrySet()) {
            String ip = entry.getKey();
            Integer weight = entry.getValue();
            // 根据权重不同,放入list 中的数量等同于权重,轮询出的的次数等同于权重
            for (int ipCount =0; ipCount < weight; ipCount++) {
                ips.add(ip);
            }
        }
        return ips;
    }

    public String weightRobin(){
        List<String> ips = this.getServerIpByWeight();
        if (index >= ips.size()){
            index = 0;
        }
        String serverIp= ips.get(index);
        index ++;
        return  serverIp;
    }

    public static void main(String[] args) {
        TestWeight testWeightRobin=new TestWeight();
        for (int i =0;i< 10 ;i++){
            String server=testWeightRobin.weightRobin();
            System.out.println(server);
        }
    }
}

输出结果:

192.168.1.1
192.168.1.3
192.168.1.3
192.168.1.3
192.168.1.3
192.168.1.2
192.168.1.2
192.168.1.1
192.168.1.3
192.168.1.3

加权随机法

获取带有权重的随机数字,随机这种东西,不能看绝对,只能看相对,我们不用index 控制下标进行轮询,只用random 进行随机取ip,即实现算法。

package com.monkeyjava.learn.basic.robin;

import java.util.*;

public class TestRandomWeight {

    static Map<String, Integer> ipMap=new HashMap<String, Integer>(16);
    static {
        // 1.map, key-ip,value-权重
        ipMap.put("192.168.1.1", 1);
        ipMap.put("192.168.1.2", 2);
        ipMap.put("192.168.1.3", 4);

    }

    public List<String> getServerIpByWeight() {
        List<String> ips = new ArrayList<String>(32);
        for (Map.Entry<String, Integer> entry : ipMap.entrySet()) {
            String ip = entry.getKey();
            Integer weight = entry.getValue();
            // 根据权重不同,放入list 中的数量等同于权重,轮询出的的次数等同于权重
            for (int ipCount =0; ipCount < weight; ipCount++) {
                ips.add(ip);
            }
        }
        return ips;
    }

    public String randomWeightRobin(){
        List<String> ips = this.getServerIpByWeight();
        //循环随机数
        Random random=new Random();
        int index =random.nextInt(ips.size());
        String serverIp = ips.get(index);
        return  serverIp;
    }

    public static void main(String[] args) {
        TestRandomWeight testRandomWeightRobin=new TestRandomWeight();
        for (int i =0;i< 10 ;i++){
            String server= testRandomWeightRobin.randomWeightRobin();
            System.out.println(server);
        }
    }
}

输出结果:

192.168.1.3
192.168.1.3
192.168.1.2
192.168.1.1
192.168.1.2
192.168.1.1
192.168.1.3
192.168.1.2
192.168.1.2
192.168.1.3

随机法

负载均衡方法随机的把负载分配到各个可用的服务器上,通过随机数生成算法选取一个服务器,这种实现算法最简单,随之调用次数增大,这种算法可以达到没台服务器的请求量接近于平均。

package com.monkeyjava.learn.basic.robin;

import com.google.common.collect.Lists;

import java.util.List;
import java.util.Random;

public class TestRandom {


    private List<String> ips = Lists.newArrayList("192.168.1.1", "192.168.1.2", "192.168.1.3");


    public String randomRobin(){
        //随机数
        Random random=new Random();
        int index =random.nextInt(ips.size());
        String serverIp= ips.get(index);
        return  serverIp;

    }

    public static void main(String[] args) {
        TestRandom testRandomdRobin =new TestRandom();
        for (int i=0;i< 10 ;i++){
            String serverIp= testRandomdRobin.randomRobin();
            System.out.println(serverIp);
        }
    }
}

输出结果:

192.168.1.3
192.168.1.3
192.168.1.1
192.168.1.2
192.168.1.1
192.168.1.3
192.168.1.2
192.168.1.3
192.168.1.3
192.168.1.2

IP_Hash算法

hash(ip)%N算法,通过一种散列算法把客户端来源IP根据散列取模算法将请求分配到不同的服务器上。

优点:保证了相同客户端IP地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的session会话。

缺点: 如果服务器进行了下线操作,源IP路由的服务器IP就会变成另外一台,如果服务器没有做session 共享话,会造成session丢失。

package com.monkeyjava.learn.basic.robin;

import com.google.common.collect.Lists;

import java.util.List;

public class TestIpHash {


    private List<String> ips = Lists.newArrayList("192.168.1.1", "192.168.1.2", "192.168.1.3");


    public String ipHashRobin(String clientIp){
        int hashCode=clientIp.hashCode();
        int serverListsize=ips.size();
        int index = hashCode%serverListsize;
        String serverIp= ips.get(index);
        return  serverIp;

    }

    public static void main(String[] args) {
        TestIpHash testIpHash =new TestIpHash();
        String servername= testIpHash.ipHashRobin("192.168.88.2");
        System.out.println(servername);
    }
}

输出结果:

192.168.1.3

 

 

使用Docker封印深信服EasyConnect

写这篇博客前先编个故事,就在半个月前我的苹果Mac Book Pro 2017款莫名无法开机,去万象城咨询售后说是主板坏维修需要4000人民币然后委婉的告诉我关注一下今年的新款。关于这款苹果笔记本电脑前前后后投入了不少钱,平均年用机成本高达5000多人民币,我只想说2015款之后再无Mac Book Pro。现在手里使用的是2012年的华硕笔记本花掉小400人民币升级到16G内存,系统盘使用的是朗科128G固态,光驱位改造成机械硬盘,整体上看性能尚可撸代码问题不大,竟然宝刀未老那就再战5年吧。

关于台式机

公司配发的台式机在我刚进公司那会儿让我做成了虚拟化的服务器7*24小时服务已经默默的运行了差不多4年,我使用它来学习集群高可用、分布式、微服务、Docker、搭建科学上网网关。

上图中编号为999是我搭建的openwrt网关它内置passwall服务我使用它来进行科学上网,我的笔记本电脑以及编号为100和101的两台虚拟机使用openwrt作为网关,这样的好处是不用任何设置即可科学上网。编号为101的windows7虚拟机我使用USB无线网卡提供WIFI服务这样我的手机也可以正常的科学上网。

创建macvlan网络

在docker中创建macvlan网络我们可以简单的理解为类似于VMware虚拟机中的桥接网络,而docker中的桥接网络相当于Vmware中的NAT网络。

docker network create -d macvlan --subnet=192.168.210.0/24 --gateway=192.168.210.254 -o parent=eth0 -o macvlan_mode=bridge docker_macvlan

封印Easyconnect

# 无代理版本
docker run -itd \
 --name easyconnect \
 --hostname easyconnect \
 --device /dev/net/tun \
 --cap-add NET_ADMIN \
 -v $PWD/easyconnect_data/root:/root \
 -v $PWD/easyconnect_data/logs:/usr/share/sangfor/EasyConnect/resources/logs \
 -e EC_VER=7.6.3 \
 -e EXIT=1 \
 -e NODANTED=1 \
 -e CLI_OPTS="-d 链接地址 -u 账号 -p 密码" \
 --net docker_macvlan \
 --ip IP地址 \
 --dns DNS地址 \
 hagb/docker-easyconnect:cli
# 有代理版本
docker run -itd \
 --name easyconnect \
 --hostname easyconnect \
 --device /dev/net/tun \
 --cap-add NET_ADMIN \
 -v $PWD/easyconnect_data/root:/root \
 -v $PWD/easyconnect_data/logs:/usr/share/sangfor/EasyConnect/resources/logs \
 -e EC_VER=7.6.3 \
 -e EXIT=1 \
 -e CLI_OPTS="-d 链接地址 -u 账号 -p 密码" \
 --net docker_macvlan \
 --ip IP地址 \
 --dns DNS地址 \
 hagb/docker-easyconnect:cli

我使用的是无代理的版本,因为我使用自己的openwrt虚拟机作为网关我只需要配置一个静态路由即可正常访问Easyconnect之后的网络。

OpenWRT静态路由

# 使用route命令添加路由
route add -net 172.16.0.0/16 gw 192.168.210.232
route add -net 172.17.0.0/16 gw 192.168.210.232

 

挂载磁盘不行那我们就创建软连接吧

关于Linux我比较提倡的学习方法是在使用中学习总结。最近在我的腾讯云服务器部署了套DzzOffice开源网盘系统,因为系统盘只有40G数据盘200G挂载给了/data目录,已经没有多余的磁盘挂载给/var/www目录我想在未来的某一天系统盘肯定不够用从而导致其他的问题,思索了好一会儿想到了创建软连接的方法来解决这个问题。

系统盘:40G

数据盘:200G

网站根目录:/var/www(实际占用系统盘)

解决办法:将网站根目录备份到数据盘/data/var/www目录然后删除/var/www目录,最后创建软连接指向到/data/var/www。

ln -s /data/var/www /var/www

 

在Linux中查询CPU的核数

以一台Linux服务器为例。这台Linux包括一颗Intel(R) Xeon(R) CPU E3-1230 v2 @ 3.30GHz CPU, 单颗CPU包括 4 个 cpu core, 使用超线程包含8个逻辑cpu core。

下面让我们通过Linux的命令来查找对应的参数,看看是否符合官方的介绍, 主要是查看/proc/cpuinfo的信息获得。

查看 CPU 的型号

cat /proc/cpuinfo | grep 'model name' | sort | uniq

输出:

model name      : Intel(R) Xeon(R) CPU E3-1230 V2 @ 3.30GHz

查看 CPU 颗数

实际Server中插槽上的CPU个数, 物理cpu数量,可以数不重复的 physical id个数。

cat /proc/cpuinfo | grep 'physical id' | sort | uniq | wc -l

输出:

1

查看 CPU 核数

一颗CPU上面能处理数据的芯片组的数量。

cat /proc/cpuinfo |grep "cores"|uniq|awk '{print $4}'

输出:

4

逻辑 CPU 核数

一般情况,我们认为一颗cpu可以有多核,加上intel的超线程技术(HT), 可以在逻辑上把一个物理线程模拟出两个线程来使用,使得单个核心用起来像两个核一样,以充分发挥CPU的性能,

逻辑CPU数量=物理cpu数量 x cpu cores 这个规格值 x 2(如果支持并开启超线程)。

top命令查询出来的就是逻辑CPU的数量。

cat /proc/cpuinfo |grep "processor"|wc -l

输出:

8

参考资料

https://stackoverflow.com/questions/6481005/how-to-obtain-the-number-of-cpus-cores-in-linux-from-the-command-line

https://blog.csdn.net/dba_waterbin/article/details/8644626

https://www.zhihu.com/question/28472793

使用Docker搭建HFish蜜罐陷阱

几个星期以前我试着使用Docker搭建了一套基于HFish的蜜罐系统,从现有掌握的数据来看主要的攻击来自境外也许攻击者们对北京地区的机房比较感兴趣,绝大多数的攻击都是ssh弱口令扫描。我搭建这套蜜罐系统需求是收集弱口令字典以及将恶意IP通过web hook加入到iptables中。

HFish

HFish是一款安全、简单可信赖的跨平台蜜罐软件,允许商业和个人用户免费使用。

特点

安全可靠:主打低中交互蜜罐,简单有效;

蜜罐丰富:支持SSH、FTP、TFTP、MySQL、Redis、Telnet、VNC、Memcache、Elasticsearch、Wordpress、OA系统等10多种蜜罐服务,支持用户制作自定义Web蜜罐;

开放透明:支持对接微步在线X社区API、五路syslog输出、支持邮件、钉钉、企业威胁、飞书、自定义WebHook告警输出;

快捷管理:支持单个安装包批量部署,支持批量修改端口和服务;

跨平台:支持Linux x32/x64/ARM、Windows x32/x64平台;

架构

HFish由控制端和节点端组成,控制端用来生成和管理节点端,并接收、分析和展示节点端回传的数据,节点端接受控制端的控制并负责构建蜜罐服务。

基于Docker容器搭建HFish

建议将自己服务器上已安装的SSH、Mysql、FTP等服务端口号改为10000端口以上,保证不跟HFish冲突。

端口说明

21为FTP端口
22为SSH端口
23为Telnet端口
69为TFTP端口
3306为Mysql端口
5900为VNC端口
6379为Redis端口
8080为暗网端口
8081为HTTP代理池端口
8989为插件端口
9000为Web端口
9001为系统管理后台端口
9200为Elasticsearch端口
11211为Memcache端口

创建volume卷

docker volume create hfish_data

部署容器

默认帐号密码均为:admin

docker run -itd \
--name hfish \
-p 21:21 \
-p 22:22 \
-p 23:23 \
-p 69:69 \
-p 3306:3306 \
-p 5900:5900 \
-p 6379:6379 \
-p 8080:8080 \
-p 8081:8081 \
-p 8989:8989 \
-p 9000:9000 \
-p 9001:9001 \
-p 9200:9200 \
-p 11211:11211 \
-v hfish_data:/opt
--restart=always \
imdevops/hfish:latest

添加防火墙规则

iptables -t nat -A POSTROUTING -m addrtype --src-type LOCAL -o docker0 -j MASQUERADE
service iptables save

数据大屏

这个数据大屏看起来挺唬人但是有个Bug,在右上角的时间以及中间列表区域的攻击时间与真实时间不一致。

Docker容器获取客户端真实IP

在前面的博文中我提到过服务器被脚本小子非法攻击的问题,然后萌生部署一套开源蜜罐系统的想法。经过一番折腾部署好基于Docker容器的HFish蜜罐系统后发现系统采集到的恶意攻击IP都来自于172.19.0.1,很显然这是Docker网络中的网关IP,根据以往经验的判断应该是iptables中nat规则配置上的问题,限于iptables体系知识储备不足,经过一番google后我找到了解决方案,在文末我会放置原文链接如果你也遇到这样的问题不妨一试。

伪装IP尤其需要以下规则

iptables -t nat -A POSTROUTING -m addrtype --src-type LOCAL -o docker0 -j MASQUERADE

iptables -t nat -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE

service iptables save

原文链接

https://stackoom.com/question/30IQE/

Docker容器分配固定IP

最近在给数据库存量用户数据做数据清洗加上京东自动签到脚本导致服务器CPU飙高至100%,在等待了30分钟后SSH依然无法登陆服务器无奈只好硬重启,随之而来的问题是Nginx中反向代理的几个Docker容器均无法正常访问,主要的原因是Docker容器在重启以后是自动分配IP与Nginx中反向代理配置的IP不一致所以导致无法访问,找到了问题的原因那就试着解决它给Docker容器分配固定IP。

创建网络

docker network create --subnet=192.168.0.0/16 staticnet

使用docker network ls命令可以查看Docker中已存在的网络清单,通过以上命令你将会看到staticnet网络。

创建Dokcer容器并指定IP

docker run -it --name userserver --net staticnet --ip 192.168.0.2 ubuntu /bin/bash

使用docker inspect {容器名称或容器ID}可查看容器IP。

通过以上几个步骤可以给Docker容器分配固定IP,容器重启IP也不会改变。

使用fail2ban保护您的服务器

一直以来我的服务器经常被一群脚本小子非法扫描很是令人讨厌,比较万幸的是经过我细心照料也从来没有被成功攻破,这得益于从业多年小心谨慎的态度保障了服务器的安全运行。

什么是Fail2ban

Fail2Ban是一个入侵检测系统框架,它可以保护电脑服务器免受蛮力攻击。以Python程式设计语言编写,并能够在类Unix系统上运行,这些系统具有本地安装的封包控制系统或防火墙的界面,例如Iptables或TCP Wrapper。

1、Fail2ban 跟 DenyHosts是类似的工具,可以阻挡有人恶意以字典暴力破解密码,通常应用于有开启 sshd、telnetd跟ftpd的主机上。

2、Fail2ban 的做法是将超过多次失败连线的 IP 列用 iptables(给IPv4 使用) 或 ip6tables (给IPv6使用)禁止该 IP之后的连线。

3、至于要多久之后可以再允许该 IP 再次连线可以在 Fail2ban 的设定档案内设定。

安装Fail2ban

yum -y install fail2ban

配置Fail2ban

建议将SSH端口设置在10000端口以上,这样做的好处是可以规避掉绝大多数的暴力破解

Fail2ban配置文件我这里是统一写在/etc/fail2ban/jail.local文件中

[DEFAULT]
# 禁止一周
bantime = 604800
# 忽略的IP段
ignoreip = 127.0.0.1/8 172.21.0.0/16
# 禁止动作
banaction = iptables-allports

[ssh]
enabled = true
port = 22
filter = sshd
logpath = %(sshd_log)s
findtime = 259200
maxretry = 2

[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
logencoding = utf-8
maxretry = 2

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
logencoding = utf-8
maxretry = 2

[mysqld-auth]
enabled = true
filter = mysqld-auth
port = 3306
logpath = /var/log/mysqld.log
logencoding = utf-8
findtime = 259200
maxretry = 2

基本命令解释

fail2ban-client -h           命令帮助

fail2ban-client stauts    查看配置状态

fail2ban-client status ssh        查看ssh配置状态

fail2ban-client unbanip {ip}    解封某个IP

Fail2ban演示

这里展示一下Fail2ban拦截到恶意爆破mysql密码被成功禁止的IP

[root@xuchengen ~]# fail2ban-client status mysqld-auth
Status for the jail: mysqld-auth
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     294
|  `- File list:        /var/log/mysqld.log
`- Actions
   |- Currently banned: 7
   |- Total banned:     8
   `- Banned IP list:   34.79.107.251 5.188.206.5 5.188.206.4 5.188.206.6 34.79.68.246 5.188.206.3 5.188.206.2