Fundamentals 16 min read

Intranet Penetration: Principles, NAT, and FRP Implementation

This article explains the concepts of public and private IP addresses, NAT techniques, and the principle of intranet penetration, then demonstrates how to set up and analyze the open‑source FRP framework, including configuration files and core Go code for both server and client components.

政采云技术
政采云技术
政采云技术
Intranet Penetration: Principles, NAT, and FRP Implementation

Introduction

The article introduces the concept of intranet penetration, a technique that allows developers to expose services running on a local machine to the public Internet without deploying them to a remote server. It uses tools such as Ngrok, Peanut Shell, and the open‑source FRP framework.

Public IP vs. Private IP

Public IP addresses are globally routable addresses provided by ISPs, while private IP addresses are assigned by local network gateways and are only reachable within the same LAN. Accessing a device outside its LAN requires a public IP.

NAT and Port Multiplexing (PAT)

NAT (Network Address Translation) enables multiple internal hosts to share a single public IP. Three NAT methods are described: static translation, dynamic translation, and Port Address Translation (PAT), the latter being the most widely used to alleviate IPv4 scarcity.

Intranet Penetration Principle

Intranet penetration works by establishing a tunnel between a public server and a client behind a private network. The public server forwards incoming requests to the client, effectively mapping a public IP and port to the private service.

Setting Up a Simple FRP Service

Configuration files for the FRP server (frps.ini) and client (frpc.ini) are provided. The server listens on a bind port and an optional HTTP port, while the client specifies the server address, ports, and the services to expose.

服务端设置(frps.ini):
[common]
bind_port = 7000       //此处填写客户端监听的服务端端口号
vhost_http_port = 8080 //此处填写用户访问的端口号

客户端配置(frpc.ini):
[common]
server_addr = x.x.x.x //此处填写服务端 IP 地址
server_port = 7000    //此处填写服务端配置的bind_port

[web]
type = http          //此处规定转发请求的协议类型
local_port = 80      //此处规定本地服务启动的地址
custom_domains = www.example.com   //此处可以填写自定义域名(需要在 IP 地址下配置域名解析)

FRP Core Code Analysis

Server Initialization (frps)

func runServer(cfg config.ServerCommonConf) (err error) {
    log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel, cfg.LogMaxDays, cfg.DisableLogColor)

    if cfgFile != "" {
        log.Info("frps uses config file: %s", cfgFile)
    } else {
        log.Info("frps uses command line arguments for config")
    }

    // !important 核心代码1
    svr, err := server.NewService(cfg)
    if err != nil {
        return err
    }
    log.Info("frps started successfully")
    // !important 核心代码2
    svr.Run()
    return
}

Client Initialization (frpc)

for {
    // !important 核心代码3
    conn, session, err := svr.login()
    if err != nil {
        xl.Warn("login to server failed: %v", err)
        if svr.cfg.LoginFailExit {
            return err
        }
        util.RandomSleep(10*time.Second, 0.9, 1.1)
    } else {
        // login success
        // !important 核心代码4
        ctl := NewControl(svr.ctx, svr.runID, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
        ctl.Run()
        svr.ctlMu.Lock()
        svr.ctl = ctl
        svr.ctlMu.Unlock()
        break
    }
}

Server‑to‑Client Work Connection (frps → frpc)

func (pxy *BaseProxy) GetWorkConnFromPool(src, dst net.Addr) (workConn net.Conn, err error) {
    xl := xlog.FromContextSafe(pxy.ctx)
    for i := 0; i < pxy.poolCount+1; i++ {
        // !important 核心代码5
        if workConn, err = pxy.getWorkConnFn(); err != nil {
            xl.Warn("failed to get work connection: %v", err)
            return
        }
        xl.Debug("get a new work connection: [%s]", workConn.RemoteAddr().String())
        xl.Spawn().AppendPrefix(pxy.GetName())
        workConn = frpNet.NewContextConn(pxy.ctx, workConn)
        // ...
        // !important 核心代码6
        err := msg.WriteMsg(workConn, &msg.StartWorkConn{
            ProxyName: pxy.GetName(),
            SrcAddr:   srcAddr,
            SrcPort:   uint16(srcPort),
            DstAddr:   dstAddr,
            DstPort:   uint16(dstPort),
            Error:     "",
        })
    }
}

Control Writer (frps)

func (ctl *Control) writer() {
    xl := ctl.xl
    defer func() {
        if err := recover(); err != nil {
            xl.Error("panic error: %v", err)
            xl.Error(string(debug.Stack()))
        }
    }()

    defer ctl.allShutdown.Start()
    defer ctl.writerShutdown.Done()

    encWriter, err := crypto.NewWriter(ctl.conn, []byte(ctl.serverCfg.Token))
    if err != nil {
        xl.Error("crypto new writer error: %v", err)
        ctl.allShutdown.Start()
        return
    }
    for {
        m, ok := <-ctl.sendCh
        if !ok {
            xl.Info("control writer is closing")
            return
        }
        // !important 核心代码8
        if err := msg.WriteMsg(encWriter, m); err != nil {
            xl.Warn("write message to control connection error: %v", err)
            return
        }
    }
}

Control Reader (frpc)

func (ctl *Control) reader() {
    xl := ctl.xl
    defer func() {
        if err := recover(); err != nil {
            xl.Error("panic error: %v", err)
            xl.Error(string(debug.Stack()))
        }
    }()
    defer ctl.readerShutdown.Done()
    defer close(ctl.closedCh)

    encReader := crypto.NewReader(ctl.conn, []byte(ctl.clientCfg.Token))
    for {
        m, err := msg.ReadMsg(encReader)
        if err != nil {
            if err == io.EOF {
                xl.Debug("read from control connection EOF")
                return
            }
            xl.Warn("read error: %v", err)
            ctl.conn.Close()
            return
        }
        ctl.readCh <- m
    }
}

Conclusion

The article demonstrates that understanding IP addressing, NAT, and PAT is essential for implementing intranet penetration. By configuring a public FRP server and a client, developers can expose local services securely. The detailed code analysis shows how FRP establishes and manages the tunnel between public and private networks.

goopen sourceNetworkingNATfrpIntranet Penetration
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.