@@ -11,6 +11,7 @@ import (
1111 "net/http"
1212 "os/exec"
1313 "strings"
14+ "syscall"
1415 "time"
1516
1617 gnfqueue "github.com/florianl/go-nfqueue"
@@ -40,14 +41,63 @@ func NewHttpDpiProvider(port string) (*HTTPProvider, error) {
4041func craftkeyauthresponse (keyAuth string ) []byte {
4142 var reply []byte
4243 reply = fmt .Append (reply , "HTTP/1.1 200 OK\r \n " )
43- reply = fmt .Append (reply , "Content-Type: text/plain" )
44- reply = fmt .Append (reply , "server: go-acme-nfqueue" )
45- reply = fmt .Append (reply , "Content-Length: %d\r \n " , len (keyAuth ))
44+ reply = fmt .Append (reply , "Content-Type: text/plain\r \n " )
45+ reply = fmt .Append (reply , "server: go-acme-nfqueue\r \n " )
46+ reply = fmt .Appendf (reply , "Content-Length: %d\r \n " , len (keyAuth ))
4647 reply = fmt .Append (reply , "\r \n " , keyAuth )
4748
4849 return reply
4950}
5051
52+ // craft packet
53+ func craftReplyPacketBytes (keyAuth string , inputpacket gopacket.Packet ) []byte {
54+ outbuffer := gopacket .NewSerializeBuffer ()
55+ opt := gopacket.SerializeOptions {
56+ FixLengths : true ,
57+ ComputeChecksums : true ,
58+ }
59+ inputTcp := inputpacket .Layer (layers .LayerTypeTCP ).(* layers.TCP )
60+ inputIPv4 := inputpacket .Layer (layers .LayerTypeIPv4 ).(* layers.IPv4 )
61+
62+ httplayer := gopacket .Payload (craftkeyauthresponse (keyAuth ))
63+ tcplayer := & layers.TCP {
64+ Seq : inputTcp .Ack + 1 ,
65+ // we reply back so reverse src and dst ports
66+ SrcPort : inputTcp .DstPort ,
67+ DstPort : inputTcp .SrcPort ,
68+ Ack : inputTcp .Seq + 1 ,
69+ Window : 100 ,
70+ }
71+ //check network layer
72+ // this is reply so we reverse sorce and dst ip
73+ iplayer := & layers.IPv4 {
74+ SrcIP : inputIPv4 .DstIP ,
75+ DstIP : inputIPv4 .SrcIP ,
76+ }
77+ tcplayer .SetNetworkLayerForChecksum (iplayer )
78+ gopacket .SerializeLayers (outbuffer , opt , iplayer , tcplayer , httplayer )
79+
80+ return outbuffer .Bytes ()
81+ }
82+
83+ func sendPacketv4 (packet []byte , DstIP net.IP ) {
84+ var err error
85+ DstIP = DstIP .To4 ()
86+ dst := [4 ]byte {DstIP [0 ], DstIP [1 ], DstIP [2 ], DstIP [3 ]}
87+ sk , err := syscall .Socket (syscall .AF_INET , syscall .SOCK_RAW , syscall .IPPROTO_RAW )
88+ if err != nil {
89+ panic (err )
90+ }
91+ addr := syscall.SockaddrInet4 {
92+ Port : 0 ,
93+ Addr : dst ,
94+ }
95+ err = syscall .Sendto (sk , packet , 0 , & addr )
96+ if err != nil {
97+ log .Fatal ("Sendto:" , err )
98+ }
99+ }
100+
51101// serve runs server by sniffing packets on firewall and inject response into it.
52102// iptables ://
53103func (w * HTTPProvider ) serve (domain , token , keyAuth string ) error {
@@ -101,38 +151,12 @@ func (w *HTTPProvider) serve(domain, token, keyAuth string) error {
101151 nf .SetVerdict (id , gnfqueue .NfDrop )
102152 //forge our new reply
103153 log .Infof ("got token packet" )
104- replyhttp := craftkeyauthresponse (keyAuth )
105- outputTcp := & layers.TCP {
106- Seq : inputTcp .Ack - 1 ,
107- // we reply back so reverse src and dst ports
108- SrcPort : inputTcp .DstPort ,
109- DstPort : inputTcp .SrcPort ,
110- Ack : inputTcp .Seq + uint32 (len (tcpLayer .LayerPayload ())),
111- DataOffset : 5 ,
112- PSH : true ,
113- }
114- outputTcp .Payload = replyhttp
115- //check network layer
116- outputTcp .SetNetworkLayerForChecksum (& layers.IPv4 {})
117- replypacket := gopacket .NewSerializeBuffer ()
118-
119- opts := gopacket.SerializeOptions {
120- FixLengths : true ,
121- ComputeChecksums : true ,
122- }
123- // serialize packet
124- if err := outputTcp .SerializeTo (replypacket , opts ); err != nil {
125- panic (err )
126- }
154+
155+ replypacket := craftReplyPacketBytes (keyAuth , payload )
127156 //dial validation agent
128157 // Send the modified packet back into the session
129- conn , err := net .Dial ("tcp4" , srcip .String ()+ ":" + inputTcp .SrcPort .String ())
130- if err != nil {
131- panic (err )
132- }
133- if _ , err := conn .Write (replypacket .Bytes ()); err != nil {
134- panic (err )
135- }
158+ log .Infof (string (replypacket ))
159+ sendPacketv4 (replypacket , srcip )
136160 // packet sent, end of function
137161 return 0
138162 } else {
0 commit comments