Katerina Argyraki, George Candea Arseniy Zaostrovnykh ... · Arseniy Zaostrovnykh, Solal Pirelli,...
Transcript of Katerina Argyraki, George Candea Arseniy Zaostrovnykh ... · Arseniy Zaostrovnykh, Solal Pirelli,...
VigNAT:A Formally Verified NAT
Arseniy Zaostrovnykh, Solal Pirelli, Luis Pedrosa, Katerina Argyraki, George Candea
2
Formally verify a stateful NF
with competitive performance
and reasonable human effort
3
Formally verify a stateful NF
with competitive performance
and reasonable human effort
Formally verify a stateful NF
with competitive performance
and reasonable human effort
4
Software Network Functions: Pros and Cons
● Everywhere○ OpenWRT/NetFilter, Click, RouteBricks
○ Vyatta, OpenVswitch, DPDK
● Flexibility, short time to market, but ...
5
Software Network Functions: Pros and Cons
● Everywhere○ OpenWRT/NetFilter, Click, RouteBricks
○ Vyatta, OpenVswitch, DPDK
● Flexibility, short time to market, but ...
● Bugs○ Packets of death, table exhaustion, denial of service
○ Cisco NAT, Juniper NAT, NetFilter, Windows ICS
○ Network outages already cost up to $700B/year 6
Testing: Easy but Incomplete
7
Testing: Easy but Incomplete
8
9
Formal Verification: Complete but Expensive
10
Formal Verification: Complete but Expensive——?——
Network Verification
S
D
11
Network Verification
S
D
CODE
12
MODEL
Network Verification ≠ NF Code Verification
S
D
CODE
13
14
Bits Algebras
Human effort quick slow (infeasible)
Machine effort slow (infeasible) quick
How to Verify an NF (Before Vigor)?
15
Bits Algebras
Human effort quick slow (infeasible)
Machine effort slow (infeasible) quick
How to Verify an NF (Before Vigor)?
16
Bits Algebras
Human effort quick slow (infeasible)
Machine effort slow (infeasible) quick
How to Verify an NF (Before Vigor)?
17
Bits Algebras
Human effort quick slow (infeasible)
Machine effort slow (infeasible) quick
How to Verify an NF (Before Vigor)?
Bits Algebras
Human effort quick high / infeasible
Machine effort slow (infeasible) low
Theorem Proving
18
Bits Algebras
Human effort quick high / infeasible
Machine effort slow (infeasible) low
Theorem Proving
Too complicated
19
[1] Klein, Gerwin, et al. "seL4: Formal verification of an OS kernel." Proceedings of the ACM SIGOPS 22nd symposium on Operating systems principles. ACM, 2009.
[2] Chen, Haogang, et al. "Using Crash Hoare logic for certifying the FSCQ file system." Proceedings of the 25th Symposium on Operating Systems Principles. ACM, 2015.
Bits Algebras
Human effort low high / infeasible
Machine effort high / infeasible low
Exhaustive Symbolic Execution (SymbEx)
20
Bits Algebras
Human effort low high / infeasible
Machine effort high / infeasible low
Exhaustive Symbolic Execution (SymbEx)
Credit to Jonas Wagner
Path Explosion
21
Bits Algebras
Human effort low high / infeasible
Machine effort high / infeasible low
Vigor
22
Bits Algebras
Human effort low high / infeasible
Machine effort high / infeasible low
Vigor
Plus runtime performance
23
Main Idea
24
● Split the code into two parts
● Verify each part separately
● Stitch the proofs — key challenge
Outline
● Problem Statement
● VigNAT Formal Proof
○ General Idea
○ Proof Stitching Example
● RFC Formalization
● Performance
25
Vigor: split code | verify parts | stitch proofs
26
CODE
Vigor: split code | verify parts | stitch proofs
27
Vigor: split code | verify parts | stitch proofs
28
Stateful code(data structures)
Stateless code(application logic)
29
Vigor: split code | verify parts | stitch proofs
Interface contracts
Interface contractsStateful code
(data structures)
30
Vigor: split code | verify parts | stitch proofs
Theorem Proving
Stateful code(data structures)
Stateless code(application logic)
31
Vigor: split code | verify parts | stitch proofs
Interface contracts
Stateful code(data structures)
Stateless code(application logic)
32
Vigor: split code | verify parts | stitch proofs
Interface contracts
ExhaustiveSymbolic Execution
Stateless code(application logic)
33
Vigor: split code | verify parts | stitch proofs
Symbolic models
ExhaustiveSymbolic Execution
Approximation (not trusted)
Symbolic models Stateless code
(application logic)
34
Vigor: split code | verify parts | stitch proofs
traces
Approximation (not trusted)
ExhaustiveSymbolic Execution
35
Vigor: split code | verify parts | stitch proofs
traces
Interface contracts
Interface contracts
Vigor: split code | verify parts | stitch proofs
Vigor Validator
36
traces
Interface contractsStateful code
(data structures)Stateless code
(application logic)
Vigor: split code | verify parts | stitch proofs
Vigor Validator
37
traces
ExhaustiveSymbolic ExecutionTheorem Proving
Outline
● Problem Statement
● VigNAT Formal Proof
○ General Idea
○ Proof Stitching Example
● RFC Formalization
● Performance
38
Proof Stitching: SymbEx + Theorem Proving
● Stateful code: theorem proving● Stateless code: exhaustive symbolic execution
1. Use symbolic models — rough interpretations of contracts
● Symbolic models are written in C
2. Replay call traces in a proof checker to check contracts39
Example NF Codeif (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
40
Example NF Codeif (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
41
if (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
42
Example NF Code
For Each API Function ...
43
Symbolicmodel
Formal contract
Example: Formal Contractvoid ring_pop_front(struct ring* r, struct packet* p);r is not empty andp points to valid memory ———————————— r contains one packet less andp points to a packet and p->port ≠ 9
44
Formal contract
Example: Symbolic Modelvoid ring_pop_front(struct ring* r, struct packet* p) { FILL_SYMBOLIC(p, sizeof(struct packet), "popped_packet"); ASSUME(p->port != 9);}
45
Symbolicmodel
Example NF Codeif (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
46
Use Symbolic Modelsif (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
47
Symbolicmodel
Symbolicmodel
Symbolicmodel
Symbolicmodel
Execution Traceif (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
48
Execution Traceif (!ring_full(r); assume(r1 → true
ring_push_back(r, &p);
if (!ring_empty(r); assume(r1 → false
ring_pop_front(r, &p): after(p.port ≠ 9)
49
if (!ring_full(r) && receive(&p) && p.port != 9)
ring_push_back(r, &p);
if (!ring_empty(r) && can_send()) {
ring_pop_front(r, &p);
send(&p);
}
Over-Approximation Proofr1 = ring_full(r); assume(r1 == true);
ring_push_back(r, &p);
r2 = ring_empty(r); assume(r2 == false);
ring_pop_front(r, &p);
assert(p.port ≠ 9);
50
Over-Approximation Proofr1 = ring_full(r); assume(r1 == true);
ring_push_back(r, &p);
r2 = ring_empty(r); assume(r2 == false);
ring_pop_front(r, &p);
assert(p.port ≠ 9);
51
Formal contract
Over-Approximation Proofr1 = ring_full(r); assume(r1 == true);
ring_push_back(r, &p);
r2 = ring_empty(r); assume(r2 == false);
ring_pop_front(r, &p);
assert(p.port ≠ 9);
52
⊂(covers)
Formal contract
Symbolicmodel
Outline
● Problem Statement
● VigNAT Formal Proof
○ General Idea
○ Proof Stitching Example
● RFC Formalization
● Performance
53
Formalization of the NAT RFC
● Everything happens at packet arrival
● Abstract flow table summarizes history of previous interactions
● Packet arrival timestamps — the only source of time
54
flowtable
Formalization of the NAT RFC
NATpacketpacket
flowtable
55
time
flowtable
Formalization of the NAT RFC
NATpacketpacket
NAT
NAT
packet
packet
packet
packet
56
time
time
time
flowtable
flowtable
Formalization of the NAT RFC
{flowtablebefore, time, packetin} ➡ {flowtableafter, packetout}
NAT packet
57
packet
timeflowtable
flowtable
packet
Formalization of the NAT RFC
58
time
update/create flow
expire_flows
forward/drop
flowtable
flowtable
Outline
● Problem Statement
● VigNAT Formal Proof
○ General Idea
○ Proof Stitching Example
● RFC Formalization
● Performance
59
PerformanceNo-op(DPDK)
Unverified NAT(DPDK)
VigNAT(DPDK)
60
Linux NAT(NetFilter)
Performance
61
Latency ~20 μsec
No-op(DPDK)
Unverified NAT(DPDK)
VigNAT(DPDK)
Linux NAT(NetFilter)
5.13 μsec
5.03 μsec
4.63 μsec
~20 μsec
Performance
Throughput 2.0Mpps
1.8Mpps 62
0.6Mpps
No-op(DPDK)
Unverified NAT(DPDK)
VigNAT(DPDK)
Linux NAT(NetFilter)
Latency 5.13 μsec
5.03 μsec
4.63 μsec
3.2Mpps
Human Effort (in Lines of Code)
Stateless code Stateful code(data structures)
Symbolic models Proofs of data structure library
800 1 000 400 + 325 (unvalidated DPDK)
23 000
63
Expect to reuse across many NFs
VigNAT Code Proof
Verification Friendliness of NF Code
● Low complexity○ No long/unbounded loops (except main loop)
● Well defined data structures
● Often implements widely adopted standards
64
Summary
● Vigor = symbolic execution + theorem proving
○ Stitching them is our primary contribution
● VigNAT is formally verified to comply with RFC 3022
○ Competitive performance
○ Tractable verification effort
65
It is feasible now to build a stateful NF that have both
competitive performance andformally verified semantic properties
with reasonable effort 66
Interface contractsStateful code
(verified data structures)Stateless code
(application logic)
Vigor Validator
traces
ExhaustiveSymbolic ExecutionTheorem Proving
Additional material
67
Index
68
● Experimental setup● DPDK performance report● Future work● NAT RFC formalization● Related work● Plots● Stitching details● Proof Structure
Performance Experiment
● RFC 2544● Intel Xeon E5-2667 v2 @ 3.30 GHz● 32 GB of DRAM● 82599ES 10 Gbps
Tester
DUT
69index
Performance is comparable
<DPDK perf report>
70index
Future Work
● Certify more NFs○ bridge with mac-learning,○ DMZ
● Improve automation (to reduce the effort and TCB)○ Invariant induction○ Symbolic model selection/generation
● Support Concurrency● Full system verification (Vigor + CompCert + seL4 + …)
71index
RFC 3022 Formalization
72index
Related work
73
● System software verificationseL4, CompCert, IronFleet, FSCQ, Beringer et al.
● Interoperability testing / protocol specificationMusuvathi et al., Bishop et al., Kuzniar et al., PIC
● Network configuration verification / testingSymNet {+NF testing}, BUZZ, Batfish, HSA, VeriFlow, NoD, Anteater, Panda et al., Cocoon, Xie et al.
● NF software verification : Dobrescu et al.index
Challenges
● Code
○ complexity from SymbEx viewpoint
○ unbounded number of events
○ arbitrary external interactions
● Formalize the RFC in machine readable language
● Integrate symbolic execution and theorem proving
74index
Latency
75index
Throughput
76index
Example: NF Code #define CAP 512int main() { struct packet p; struct ring *r = ring_create(CAP); if (!r) return 1; while(VIGOR_LOOP(1)) { loop_iteration_begin(&r); if (!ring_full(r)) if (receive(&p) && p.port != 9) ring_push_back(r, &p); if (!ring_empty(r) && can_send()) { ring_pop_front(r, &p); send(&p); } loop_iteration_end(&r); } return 0;} 77index
loop_iteration_begin(&X) => []ring_full(&X) => truering_empty(&X) => falsecan_send() => truering_pop_front(&X, &{.port == y} -> &{.port == z}) => []——z != 9
#define CAP 512int main() { struct packet p; struct ring *r = ring_create(CAP); if (!r) return 1; while(VIGOR_LOOP(1)) { loop_iteration_begin(&r); if (!ring_full(r)) if (receive(&p) && p.port != 9) ring_push_back(r, &p); if (!ring_empty(r) && can_send()) { ring_pop_front(r, &p); send(&p); } loop_iteration_end(&r); } return 0;}
SymbEx→ Theorem Proving:Trace
78index
loop_iteration_begin(&X) => []ring_full(&X) => truering_empty(&X) => falsecan_send() => truering_pop_front(&X, &{.port == y} -> &{.port == z}) => []——z != 9
SymbEx→ Theorem Proving:Replay
struct ring* arg1;struct packet arg2;
loop_invariant_produce(&(arg1));//@ open loop_invariant(_);bool ret1 = ring_full(arg1);//@ assume(ret1 == true);bool ret2 = ring_empty(arg1);//@ assume(ret2 == false);bool ret3 = can_send();//@ assume(ret3 == true);/*@ close packetp(&(arg2), packet((&(arg2))->port));@*/ring_pop_front(arg1, &(arg2));//@ open packetp(&(arg2), _);
//@ assert(arg2.port != 9);79index
struct ring* arg1;struct packet arg2;
loop_invariant_produce(&(arg1));//@ open loop_invariant(_);bool ret1 = ring_full(arg1);//@ assume(ret1 == true);bool ret2 = ring_empty(arg1);//@ assume(ret2 == false);bool ret3 = can_send();//@ assume(ret3 == true);/*@ close packetp(&(arg2), packet((&(arg2))->port));@*/ring_pop_front(arg1, &(arg2));//@ open packetp(&(arg2), _);
//@ assert(arg2.port != 9);
SymbEx→ Theorem Proving:Replay
void ring_pop_front(struct ring* ...);Contract: ... andpacket satisfies packet_constraints_fp.
80index
Proof Structure VigNAT satisfies semantic properties
VigNAT satisfieslow-level properties
VigNAT stateless coderespects the
interface contracts
symbolic models are faithful to the
interface contracts
Stateful implementations behaves according to the
interface contracts
81index