四元组
[源IP] + [源端口] + [目标IP] + [目标端口]
五元组
[协议] + [源IP] + [源端口] + [目标IP] + [目标端口]
- 由于目标IP、目标端口是固定的,可以通过构造不同的源IP和源端口用于发起连接,从而达到建立百万连接的目的
构造源IP
- 查看IP信息
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.2.11 netmask 255.255.255.0 broadcast 192.168.2.255
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
- 添加IP(添加
20
个即可,每个ip发起52000
个连接可以达到百万连接了)
sudo ip address add 192.168.2.12 dev eth0
sudo ip address add 192.168.2.13 dev eth0
...
示例代码
package main
import (
"fmt"
"os"
"time"
"github.com/ikilobyte/netman/iface"
"github.com/ikilobyte/netman/server"
)
type Ping struct {
}
func (p *Ping) Do(request iface.IRequest) {
//fmt.Printf("recv PING %d %s\n", request.GetConnect().GetID(), time.Now().String())
}
func main() {
fmt.Println(os.Getpid())
s := server.New("0.0.0.0", 6565, server.WithMaxBodyLength(0))
go func() {
ticker := time.NewTicker(time.Second * 5)
for {
select {
case <-ticker.C:
fmt.Printf("total connection %d\n", s.TotalConnect())
}
}
}()
s.AddRouter(0, new(Ping))
s.Start()
}
启动服务端
ulimit -n 1200000
go run .
示例代码
package main
import (
"flag"
"fmt"
"log"
"net"
"sync"
"time"
"github.com/ikilobyte/netman/util"
)
var device = flag.String("device", "eth0", "网卡名称")
var total = flag.Int("total", 10, "每个IP发起的数量")
var server = flag.String("server", "", "服务器地址")
func main() {
flag.Parse()
if *server == "" {
log.Panicln("请传入服务器地址")
}
ips := getIps(*device)
if len(ips) <= 0 {
log.Panicln("没有可用的IP地址")
}
fmt.Printf("ips %v total %d\n", ips, len(ips))
time.Sleep(time.Second * 10)
for _, ip := range ips {
go connect(ip)
}
select {}
}
func getIps(value string) []net.IP {
result := make([]net.IP, 0)
name, err := net.InterfaceByName(value)
if err != nil {
panic(err)
}
addrs, err := name.Addrs()
if err != nil {
panic(err)
}
for _, addr := range addrs {
ipNet, ok := addr.(*net.IPNet)
if ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
result = append(result, ipNet.IP.To4())
}
}
}
return result
}
func connect(ip net.IP) {
var wg sync.WaitGroup
c := make(chan net.Conn, 512)
go func() {
list := make([]net.Conn, 0, 51000)
ticker := time.NewTicker(time.Second * 5)
for {
select {
case <-ticker.C:
fmt.Printf("ip %v connect %d\n", ip, len(list))
case conn := <-c:
list = append(list, conn)
}
}
}()
packer := util.NewDataPacker()
// 每个IP地址发起的连接数
for i := 0; i < *total; i++ {
wg.Add(1)
go func(port int) {
defer wg.Done()
conn, err := net.DialTCP("tcp",
&net.TCPAddr{IP: ip, Port: port + 10000},
&net.TCPAddr{IP: net.ParseIP(*server), Port: 6565},
)
if err != nil {
fmt.Printf("connect err by port %d err %v\n", port, err)
return
}
c <- conn
for {
pack, _ := packer.Pack(0, []byte("PING"))
conn.Write(pack)
time.Sleep(time.Second * 10)
}
}(i)
time.Sleep(time.Millisecond * 10)
}
wg.Wait()
}
启动客户端
ulimit -n 1200000
go run . --server xxx.xx.xx.xx --device xxx