<style>
img {
border-radius: 10px;
border: 2px solid #BDC3C7;
}
</style>

# 緣由
最近在工作上,例行的檢查AWS **applicaiton loadbalancer** 的monitoring tab時,發現了其中一格神祕的資訊:

事實上,這個資訊看過多次,但是一直不了解它代表了甚麼意義。查詢了aws 的 **knowledge base**,aws建議可以用**ssl-scan**去檢查attach在loadbalancer上面的certificate。然而,我們的certificate是**ACM** (AWS Certificate Manager)所派發的,基本上不會有問題才是。
> https://repost.aws/knowledge-center/elb-fix-ssl-tls-negotiation-error
接著,我去下載了loadbalancer的access log,但log沒有看到任何關於*Client TLS negotiation errors*的紀錄。
> 例如,access log的欄位解讀: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html
查找了網路上的資訊,發現有人利用AWS的VPC traffic mirroring 來capture loadbalancer的封包,除錯 *Client TLS negotiation errors*的發生原因。基於好奇心,我們來做個實驗吧!
# VPC Traffic Mirroring 概念
- 簡單來說,只要是resource具有`ENI` (Elastic Network Interface),理論上都可以透過traffic mirroring的方式擷取封包。

(出處: https://www.qacafe.com/resources/aws-vpc-traffic-mirroring-cloud-packet-capture/)
- 決定source以及target的`ENI`。
- Source是applicaiton loadbalancer。
- application loadbalancer的ENI在哪裡可以查到?
- Target是同VPC內的某台EC2。
## VXLAN
AWS 利用 VXLAN protocol 來包裝封包:

> https://docs.aws.amazon.com/vpc/latest/mirroring/traffic-mirroring-packet-formats.html
## 取得 application loadbalancer的資訊
```shell
aws elbv2 describe-load-balancers --names mvb-eco-sys-ws-prod --region eu-central-1
```
```JSON
{
"LoadBalancers": [
{
"LoadBalancerArn": "arn:aws:elasticloadbalancing:eu-central-1:******************:loadbalancer/app/mvb-eco-sys-ws-prod/741****************",
"DNSName": "************.eu-central-1.elb.amazonaws.com",
"CanonicalHostedZoneId": "**************",
"CreatedTime": "2021-01-13T10:34:40.780000+00:00",
"LoadBalancerName": "mvb-eco-sys-ws-prod",
"Scheme": "internet-facing",
"VpcId": "vpc-***************",
"State": {
"Code": "active"
},
"Type": "application",
"AvailabilityZones": [
{
"ZoneName": "eu-central-1a",
"SubnetId": "subnet-******************",
"LoadBalancerAddresses": []
},
{
"ZoneName": "eu-central-1b",
"SubnetId": "subnet-******************",
"LoadBalancerAddresses": []
}
],
"SecurityGroups": [
"sg-******************"
],
"IpAddressType": "ipv4"
}
]
}
```
## 取得applicaiton loadbalancer ENI列表
```shell
aws ec2 describe-network-interfaces --filters Name=description,Values="ELB app/mvb-eco-sys-ws-prod/******************" --query 'NetworkInterfaces[*]' --output json --region eu-central-1 | jq -c '.[].NetworkInterfaceId'
```
> "eni-0a2bf36cdb1c57099"
> "eni-00d05507cd1140898"
> "eni-080477509901b6a76"
> "eni-0e2c5f664c663abc9"
> "eni-0905dc9871ecab671"
> "eni-0292a0604baf86b91"
> "eni-0a1f1ad189baaa7df"
> "eni-0a2c8d84bd7953b08"
> "eni-05cccf1718fbaf35f"
> "eni-06862fbbad18b5c46"
> "eni-0c36fed47d6d0de6b"
> "eni-081934841f840b09f"
> "eni-09cbe68ac9c8f0b44"
這台loadbalancer用量比較大,所以有13張ENI !
## 什麼 ? 原來application loadbalancer是一排EC2?
其實從以前就覺得奇怪,為什麼loadbalancer跟EC2是放在同一個介面上 (EC2 Dashboard
)。原來loadbalancer本質上就是一排的EC2!
透過下面的資料可以觀察到:
```shell
aws ec2 describe-network-interfaces --filters Name=description,Values="ELB app/mvb-eco-sys-ws-prod/******************" --query 'NetworkInterfaces[*]' --output json --region eu-central-1 | jq -c '.[]."Association"."PublicDnsName"'
```
> "ec2-3-121-54-139.eu-central-1.compute.amazonaws.com"
> "ec2-3-77-159-52.eu-central-1.compute.amazonaws.com"
> "ec2-18-153-166-253.eu-central-1.compute.amazonaws.com"
> "ec2-3-120-200-244.eu-central-1.compute.amazonaws.com"
> "ec2-54-93-93-216.eu-central-1.compute.amazonaws.com"
> "ec2-52-28-50-142.eu-central-1.compute.amazonaws.com"
> "ec2-3-120-19-81.eu-central-1.compute.amazonaws.com"
> "ec2-18-198-21-139.eu-central-1.compute.amazonaws.com"
> "ec2-52-57-17-95.eu-central-1.compute.amazonaws.com"
> "ec2-3-124-82-62.eu-central-1.compute.amazonaws.com"
> "ec2-52-28-107-255.eu-central-1.compute.amazonaws.com"
> "ec2-18-157-172-87.eu-central-1.compute.amazonaws.com"
> "ec2-52-28-217-154.eu-central-1.compute.amazonaws.com"
>
# 動手做
順序:
> 1. 開啟&設定一台EC2,作為traffic mirroring 的 destination and tcpdump的執行機器
> 2. 設定VPC traffic mirroring ,啟動 mirroring。
> 3. 回到EC2,設定一個vxlan interface,使用tcpdump擷取packets。
## *EC2 - part 1*
1. 開啟一台EC2,設定好security group。
2. ssh進入EC2,安裝 conntrack and tcpdump。
```shell
sudo iptables -t filter -A INPUT -m state --state NEW\,ESTABLISHED -j ACCEPT && sudo iptables -t filter -A FORWARD -m state --state NEW\,ESTABLISHED -j ACCEPT && sudo iptables -t filter -A OUTPUT -m state --state NEW\,ESTABLISHED -j ACCEPT
```
```shell
/bin/echo "1" > /proc/sys/net/netfilter/nf_conntrack_acct
```
3. 這個時候應該還沒有任何traffic

## *VPC traffic mirroring Configuration*
### Mirror targets
設定你的EC2為 mirror target

### Mirror filters
1. 設定如下圖的 reject & accept,只擷取external traffic的資料。
2. Internal traffic VPC CIDR都去掉。

### Mirror sessions
1. 從上述的資訊,可以確定你選到正確的ENI:

## *EC2 - part 2*
1. 檢查 EC2 上面的 port 4789 是否已經有mirroring來的traffic。
```shell
sudo conntrack -L -p udp
```

2. 新增一個VXLAN interface
```shell
sudo ip link add ${interface_name} type
id ${vni} local ${EC2's local ip address} remote ${source_ip_address} dev ${interface_name_of_EC2_eni} dstport 4789
sudo ip link set ${interface_name} up
```
3. 開始抓封包
```shell
sudo tcpdump -n -i ${interface_name} -vv -w ${filename}.pcap
```
# 分析pcap
1. 把 \*.pcap下載下來,使用wireshark打開pcap檔。輸入以下的指令做filter:
```
tls.alert_message.level == 2
```
2. 輸入完後,可以發現出現了很多**Certificate Unknown - 21**的alert !

- 打開封包檔:

3. follow 某一個TLS stream,可以發現以下的封包:

## TLS Alert
> Error code 21 for TLS
> https://en.wikipedia.org/wiki/Transport_Layer_Security#Alert_protocol
>

# 題外話 - JA3
- 2017年由Saleforces的工程師提出。
> A method for profiling SSL/TLS Clients
> https://engineering.salesforce.com/open-sourcing-ja3-92c9e53c3c41/
## JA3 fingerprint如何得到 ?

The field order is as follows:
> SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats
Example:
> 769,47–53–5–10–49161–49162–49171–49172–50–56–19–4,0–10–11,23–24–25,0
MD5 Hash:
> 769,47-53-5-10-49161-49162-49171-49172-50-56-19-4,0-10-11,23-24-25,0 --> ada70206e40642a3e4461f35503241d5
> 769,4-5-10-9-100-98-3-6-19-18-99,,, --> de350869b8c85de67a350c8d186f11e6
>
## 安裝JA3套件
安裝:
```shell
pip install ja3
ja3 --json capture-ws-prod.pcap > capture-ws-prod.json
```
取得這些有同樣的ja3 fingerprint的request是從哪裡來的 ?
```shell
cat capture-ws-prod.json | jq -c '.[] | select(.ja3_digest | contains("a specificed string")) | .source_ip' | sort | uniq
> "130.255.x.x"
> "145.224.x.x"
> "182.173.x.x"
> "182.68.x.x"
> "188.209.x.x"
> ...
```
# 結論
學到了什麼?
1. 事實上,雖然我們嘗試錄了loadbalancer封包,我們無法看切確是什麼error造成的,只知道在某個特定的`JA3 fingerprint`下會有這個error。
2. 原來loadbalancer是一排EC2,隨著用量變大,機器會越來越多 !
3. `JA3 fringerprint`目前會使用資安領域,例如特定的設備、供應商client的網路足跡;作為資訊安全的一個計分。
4. 我觀察到AWS WAF 也支援這個 JA3 fingerprint:

5. VXLAN是目前資料中心廣泛採用的一種技術,實現實體網路跟抽象網路規劃的decoupling。
> https://info.support.huawei.com/info-finder/encyclopedia/zh/VXLAN.html
# Reference
1. https://repost.aws/knowledge-center/elb-fix-ssl-tls-negotiation-error
2. https://sjakthol.github.io/posts/alb-vpc-traffic-mirroring/
3. https://engineering.salesforce.com/open-sourcing-ja3-92c9e53c3c41/
4. https://aws.amazon.com/tw/about-aws/whats-new/2023/09/aws-waf-ja3-fingerprint-match/
6. https://datatracker.ietf.org/doc/html/rfc7348
8. https://docs.aws.amazon.com/zh_tw/vpc/latest/mirroring/traffic-mirroring-how-it-works.html