Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/urr #69

Merged
merged 26 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d408b76
support: URR related IEs
ianchen0119 Apr 13, 2023
dade9b5
ignore session report msg in PeekNextResponse()
ianchen0119 Apr 13, 2023
9fcaeab
print log msg when received session report related msg
ianchen0119 Apr 13, 2023
c251713
upgrade to golang 1.18 & go-pfcp v0.0.19
ianchen0119 Mar 14, 2024
77d2824
update urr related handlers
ianchen0119 Apr 13, 2023
21db935
support to handle sessionReport
ianchen0119 May 18, 2023
40b9121
add fuzz package
ianchen0119 May 30, 2023
4625047
support ie fuzzing
ianchen0119 Jun 2, 2023
222ad0d
update Fuzzing Test
ianchen0119 Mar 14, 2024
898a43e
ignore HeartbeatRequest
ianchen0119 Mar 14, 2024
d877fbd
fix ci linter error
ianchen0119 Mar 14, 2024
8907dbe
package rename
ianchen0119 Mar 14, 2024
1d69794
add license/copyright header
ianchen0119 Mar 15, 2024
d0ed6b9
update makefile
ianchen0119 Mar 15, 2024
e56d4f7
Fix lint issue
gab-arrobo Mar 15, 2024
5c81b4d
fix gosec G404 & update behavior of test target in Makefile
ianchen0119 Mar 16, 2024
9f79a09
update go.mod
ianchen0119 Mar 16, 2024
bd74ad7
fix ci-lint error in fuzz test
ianchen0119 Mar 16, 2024
11acbe7
Merge remote-tracking branch 'origin/main' into feat/urr
ianchen0119 Mar 22, 2024
6c42b46
update README
ianchen0119 Mar 22, 2024
e9dc828
fix ci linter error
ianchen0119 Mar 22, 2024
8e72c4b
fix: support loopback interface
andy89923 Mar 27, 2024
56dee82
Update .gitignore
gab-arrobo Mar 27, 2024
b373b76
fix: update typo and add args for fuzz test
andy89923 Mar 28, 2024
fecab46
doc: update README
andy89923 Mar 28, 2024
8375047
Apply suggestions from code review
gab-arrobo Mar 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2022-present Open Networking Foundation

.fuzz/test_data
.idea/
.coverage/
output
*.pyc
*.swp
*.log
client
server
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ golint:
rm -rf $(CURDIR)/.coverage
mkdir -p $(CURDIR)/.coverage

# -run flag ensures that the fuzz test won't be run
# because the fuzz test needs a UPF to run
test: .coverage
go test -race -coverprofile=.coverage/coverage-unit.txt -covermode=atomic -v ./...
go test -race -coverprofile=.coverage/coverage-unit.txt -covermode=atomic -run=^Test -v ./...
ianchen0119 marked this conversation as resolved.
Show resolved Hide resolved

reuse-lint:
docker run --rm -v $(CURDIR):/pfcpsim -w /pfcpsim omecproject/reuse-verify:latest reuse lint
Expand Down
80 changes: 79 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# pfcpsim
pfcpsim is a simulator to interact with PFCP agents. Can be used to simulate a 4G SGW-C / 5G SMF.

> All related features are implemented according to the 3GPP TS 29.244 V16.3.1(2020-04).
## Overview

pfcpsim is designed to work within a containerized environment. The docker image comes with both client (`pfcpctl`) and server (`pfcpsim`).
Expand All @@ -13,7 +14,9 @@ pfcpsim is designed to work within a containerized environment. The docker image

## Getting Started

#### 1. Create the container. Images are available on [Dockerhub](https://hub.docker.com/r/opennetworking/pfcpsim/tags):
### Normal Case

#### 1. Create the container. Images are available on [DockerHub](https://hub.docker.com/r/opennetworking/pfcpsim/tags):
```bash
docker container run --rm -d --name pfcpsim pfcpsim:<image_tag> -p 12345 --interface <interface-name>
```
Expand Down Expand Up @@ -57,6 +60,81 @@ docker exec pfcpsim pfcpctl --server localhost:12345 session delete --count 5 --
docker exec pfcpsim pfcpctl --server localhost:12345 service disassociate
```

### Fuzzing Mode

Pfcpsim is able to generate malformed PFCP messages and can be used to explore potential vulnerabilities of PFCP agents (UPF).

> Note:
> PFCP fuzzer is developed by the [Ian Chen (free5GC team)](https://github.com/ianchen0119)
> PFCP fuzzer was used to test the UPF implementation of the free5GC project, and successfully found some vulnerabilities.

To use the PFCP fuzzer, we need to prepare the fuzzing environment first. The following steps show how to use the PFCP fuzzer.

#### 1. Launch the UPF instance

Pfcpsim supports to test various UPF implementations.
You can choose the UPF implementation you want to test, and launch the UPF instance.

#### 2. Change the configuration in `fuzz/ie_fuzz_test.go`

You should change the configuration in `fuzz/ie_fuzz_test.go`:
```go=
sim := export.NewPfcpSimCfg(iface, upfN3, upfN4)
```
- `iface`: the interface name you used to establish the connection with UPF.
- `upfN3`: the N3 interface address of the UPF.
- `upfN4`: the N4 interface address of the UPF.

#### 3. Run the fuzzing test

You can run the fuzzing test by the following command:
```
go test -fuzz=Fuzz -p 1 -parallel 1 -fuzztime 15m ./fuzz/...
```
To specify args:
```
go test -fuzz=Fuzz -p 1 -parallel 1 -fuzztime 15m ./fuzz/... -args -iface=lo -upfN3=192.168.0.5 -upfN4=127.0.0.8
```
- `-fuzztime`: the time you want to run the fuzzing test.
- Do not change the value of either `-parallel` or `-p` flag because it will cause the race condition.
- The output for the fuzzing test looks like this:
```
fuzz: elapsed: 0s, gathering baseline coverage: 0/100 completed
fuzz: elapsed: 3s, gathering baseline coverage: 0/100 completed
...
fuzz: elapsed: 13m21s, gathering baseline coverage: 99/100 completed
fuzz: elapsed: 13m21s, gathering baseline coverage: 100/100 completed, now fuzzing with 1 workers
fuzz: elapsed: 13m24s, execs: 100 (0/sec), new interesting: 0 (total: 100)
...
fuzz: elapsed: 15m1s, execs: 111 (0/sec), new interesting: 0 (total: 100)
PASS
ok github.com/omec-project/pfcpsim/fuzz 900.684s
```
- If the test result shows "PASS" and the UPF didn't crash, it means that the fuzzy test was successful!
- ```
gab-arrobo marked this conversation as resolved.
Show resolved Hide resolved

- If Pfcpsim can't connect to the UPF, the user will see an output like this:
```
...
failure while testing seed corpus entry: Fuzz/seed#0
fuzz: elapsed: 5s, gathering baseline coverage: 0/106 completed
--- FAIL: Fuzz (5.02s)
--- FAIL: Fuzz (5.00s)
ie_fuzz_test.go:57:
Error Trace: /home/xxxx/pfcpsim/fuzz/ie_fuzz_test.go:57
/usr/local/go/src/reflect/value.go:556
/usr/local/go/src/reflect/value.go:339
/usr/local/go/src/testing/fuzz.go:337
Error: Received unexpected error:
route ip+net: no such network interface
Test: Fuzz
Messages: InitPFCPSim failed

FAIL
exit status 1
FAIL github.com/omec-project/pfcpsim/fuzz 5.023s
```

## Compile binaries
If you don't want to use docker you can just compile the binaries of `pfcpsim` and `pfcpctl`:

Expand Down
94 changes: 94 additions & 0 deletions fuzz/ie_fuzz_test.go
ianchen0119 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-present Ian Chen <ychen.cs10@nycu.edu.tw>

package fuzz

import (
"crypto/rand"
"flag"
"math/big"
"testing"
"time"

"github.com/omec-project/pfcpsim/internal/pfcpsim/export"
"github.com/omec-project/pfcpsim/pkg/pfcpsim/session"
"github.com/stretchr/testify/require"
)

const (
MaxUint = ^uint(0)
MaxInt = int(MaxUint >> 1)
)

func getRand(n int) int {
res, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
if err != nil {
return n
}

return int(res.Int64())
}

var (
iface = flag.String("iface", "eth0", "the interface name you used to establish the connection with UPF.")
upfN3 = flag.String("upfN3", "192.168.0.5", "the N3 interface address of the UPF")
upfN4 = flag.String("upfN4", "127.0.0.8", "the N4 interface address of the UPF")
)

func Fuzz(f *testing.F) {
var testcases []uint
for i := 0; i < 100; i++ {
testcases = append(testcases, uint(getRand(MaxInt)))
}

for _, tc := range testcases {
f.Add(tc)
}

session.SetCheck(false)

f.Fuzz(func(t *testing.T, input uint) {
time.Sleep(5 * time.Second)

sim := export.NewPfcpSimCfg(*iface, *upfN3, *upfN4)

err := sim.InitPFCPSim()
if err != nil {
require.NoError(t, err, "InitPFCPSim failed")
}

err = sim.Associate()
if err != nil {
require.NoError(t, err, "Associate failed")
}

defer func() {
err = sim.TerminatePFCPSim()
require.NoError(t, err)
}()

err = sim.CreateSession(2, getRand(session.PdrMax),
int(input)%session.QerMax,
int(input)%session.FarMax,
int(input)%session.UrrMax,
input)
if err != nil {
require.NoError(t, err, "CreateSession failed")
}

err = sim.ModifySession(2,
getRand(session.FarMax),
getRand(session.UrrMax),
input)
if err != nil {
require.NoError(t, err, "ModifySession failed")
}

time.Sleep(3 * time.Second)

err = sim.DeleteSession(2)
if err != nil {
require.NoError(t, err, "DeleteSession failed")
}
})
}
24 changes: 12 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ module github.com/omec-project/pfcpsim
go 1.21

require (
github.com/c-robinson/iplib v1.0.3
github.com/golang/protobuf v1.5.2
github.com/c-robinson/iplib v1.0.6
github.com/golang/protobuf v1.5.3
github.com/jessevdk/go-flags v1.5.0
github.com/pborman/getopt/v2 v2.1.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
github.com/wmnsk/go-pfcp v0.0.14
google.golang.org/grpc v1.44.0
google.golang.org/protobuf v1.27.1
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.9.0
github.com/wmnsk/go-pfcp v0.0.19
google.golang.org/grpc v1.54.0
google.golang.org/protobuf v1.30.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading