首先检查当前系统的linux kernel有没有支持ppp, netfilter, mppe和 netfilter的nat,如果没有,请先配置支持这些组建,编译更新内核,然后重启系统。这块不再详述,如果想知道详细情况,可以留言问我。
接着安装必要软件

emerge ppp

emerge pptpd

然后修改配置文件
先是pptpd的配置文件 /etc/pptpd.conf

1
2
3
4
5
ppp /usr/sbin/pppd
option /etc/ppp/options.pptpd
logwtmp
localip 172.16.0.1
remoteip 172.16.0.2-254

协议规范

实现原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
struct ppp_info{
int unit; /**/
int dev_fd; /**/
int lcp_fd; /**/
int ppp_fd; /**/
int remote_id; /**/
char *user; /* Username for authentication */
char *passwd; /* Password for authentication */
char *ifname;
char attach_inter[16];
unsigned char distance;
unsigned char weight;
unsigned char gateway;
unsigned char dns;
unsigned char auth;
unsigned char auth_type;
unsigned char down_flag; //避免PPP主动down掉和手动清除冲突
unsigned int unique;
unsigned int dns_value;
unsigned int wins_value;
char usergrp[MAXNAMELEN];
struct prefix_ipv4 localaddr;
unsigned int peer_address; //tunnip
int lcp_detect_interval_time; //for change interval time of lcp echo request
int lcp_detect_lost_times; //for change times of no respons lcp echo request
struct thread * lcp_thread;
struct thread * ipcp_rthread;
void *conn;
void *priv_data;
int natid;
int mtu;
Ppp_if_type iftype;
int (*manage_auto_down) (char *ifname);
int (*ipcp_up_cb) (struct ppp_cb_info *cb_info);
int (*ipcp_down_cb) (struct ppp_cb_info *cb_info);
int (*lcp_auth) (char *name, char *group, char *password, unsigned char *challenge, int unit, int type);
int (*check_rqci)(__u32 addr);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pty.h>
int main()
{
int fd_m, fd_s;
int len;
const char *pts_name;
char send_buf[64] = "abc\ndefghijk\nlmn";
char recv_buf[64] = {0};
fd_m = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (fd_m < 0) {
printf("open /dev/ptmx fail1\n");
return -1;
}
if (grantpt(fd_m) < 0 || unlockpt(fd_m) < 0) {
printf("grantpt and unlockpt fail\n");
goto err;
}
pts_name = (const char *)ptsname(fd_m);
fd_s = open(pts_name, O_RDONLY | O_NOCTTY);
if (fd_s < 0) {
printf("open /dev/ptmx fail2\n");
goto err;
}
len = write(fd_m, send_buf, strlen(send_buf));
printf("write len=%d\n", len);
len = read(fd_s, recv_buf, sizeof(recv_buf));
printf("read len=%d, recv_buf=[%s]\n", len, recv_buf);
len = read(fd_s, recv_buf, sizeof(recv_buf));
printf("read len=%d, recv_buf=[%s]\n", len, recv_buf);
close(fd_m);
close(fd_s);
return 0;
err:
if (fd_m)
close(fd_m);
if (fd_s)
close(fd_s);
return -1;
}

1,前提条件

环境 系统类型 本地用户 SSH服务端口
A机位于公司的NAT网络 安装在VMware里的Debian 8 64bit虚拟机 userA 22
B机是一台有公网IP的VPS CentOS 6 64bit userVPS 1022
C机位于家庭的NAT网络 Windows系统

实现目的:使得位于家庭NAT网络内的C机,可以SSH访问位于公司NAT网络内的A机。